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:学习使用调试器。这会直接指向指令,然后你可能自己就能解决问题