Linux 基于用户输入的汇编调用子程序
我有一个程序,可以根据用户输入的Linux 基于用户输入的汇编调用子程序,linux,assembly,input,x86,att,Linux,Assembly,Input,X86,Att,我有一个程序,可以根据用户输入的0或非0对两个硬编码数字进行加法或减法运算。我在输入中得到内存访问冲突错误。当我尝试在第9行调用sum或调用diff而不是input时,它工作正常,并提供了预期的输出循环和下一步用于显示堆栈的结果 .text .global _start _start: xorl %esi, %esi # zerowanie licznika call input # <---- line 9 loop:
0
或非0
对两个硬编码数字进行加法或减法运算。我在输入中得到内存访问冲突错误。当我尝试在第9行调用sum
或调用diff
而不是input
时,它工作正常,并提供了预期的输出<代码>循环
和下一步
用于显示堆栈的结果
.text
.global _start
_start:
xorl %esi, %esi # zerowanie licznika
call input # <---- line 9
loop: # label
movl $0, %edx # reszta z dzielenia
movl $10, %ebx # dzielnik
divl %ebx # dzielenie, wynik w eax, reszta w edx
addl $48, %edx # kod ASCII
pushl %edx # edx na stos
incl %esi # esi++
cmpl $0, %eax # porównaj wynik i 0
jz next # jeśli koniec, jump next
jmp loop # jeśli nie, następna iteracja
next: # label
cmpl $0, %esi # porównaj licznik z 0
jz exit # jeśli koniec, jump exit
decl %esi # esi--
movl $4, %eax # kod 4 = zapis
movl %esp, %ecx # znak do wypisania
movl $1, %ebx # domyślny strumień - sys_out
movl $1, %edx # długość stringa do wypisania?
int $0x80 # przerwanie
addl $4, %esp #
jmp next # kolejna iteracja
exit:
mov $1, %eax # zakończenie programu
mov $0, %ebx # kod wyjścia
int $0x80 # przerwanie
# ---------------- subprogram ----------------------
input:
movl $3, %eax # code 3 = input
movl $0, %ebx # code 0 = stdin
subl $4, %esp # move stack pointer by 4 bytes
movl %esp, %ecx # set reading position onto stack
movl $4, %edx # read 4 bytes
int $0x80 # interrupt to execute above
cmp %esp, '0' # if(input == '0') sum else diff
jz sum
jnz diff
ret
sum:
movl $37, %eax # pierwsza liczba sumy
movl $22, %ebx # druga liczba sumy
addl %ebx, %eax # suma, wynik w eax
ret
diff:
movl $37, %eax # pierwsza liczba sumy
movl $22, %ebx # druga liczba sumy
subl %ebx, %eax # roznica, wynik w eax
ret
# ------------- end -------------
.text
.全球启动
_开始:
xorl%esi,%esi#zerowanie-licznika
调用输入#cmp%esp,'0'
是错误的,因为它试图将%esp
的值与内存中地址'0'
处的值进行比较。At&t语法使用反向操作数,它需要一个$
前缀来表示立即数。但你已经知道了,我猜你只是有点粗心。正确的指令是cmpb$'0',(%esp)
,用于将地址%esp
处内存中的字节与0
的ascii码进行比较
此外,您从堆栈中分配了4个字节,但从未释放该字节。当您最终点击一个ret
时,它将使用您的局部变量作为返回地址,这当然是一件坏事:)一个很好的技巧是使用lea4(%esp),%esp
释放它而不影响标志,因此您可以在cmp
和jz
之间执行此操作。如果您喜欢不那么复杂的东西,您当然可以将输入弹出到寄存器中,并在比较中使用它,例如:
pop %eax
cmp $'0', %al
PS:学习使用调试器。这会直接指向指令,然后你可能自己就能解决问题