基于用户输入的汇编调用子程序
Assembly call subprograms based on user input
我有一个程序应该根据用户输入 0
或 not 0
添加或减去两个硬编码数字。我在 input
中收到内存访问冲突错误。当我在第 9 行尝试 call sum
或 call diff
而不是 input
时,它工作正常并给出了预期的输出。 loop
和 next
用于显示堆栈的结果。
.text
.global _start
_start:
xorl %esi, %esi # zerowanie licznika
call input # <---- line 9
loop: # label
movl [=10=], %edx # reszta z dzielenia
movl , %ebx # dzielnik
divl %ebx # dzielenie, wynik w eax, reszta w edx
addl , %edx # kod ASCII
pushl %edx # edx na stos
incl %esi # esi++
cmpl [=10=], %eax # porównaj wynik i 0
jz next # jeśli koniec, jump next
jmp loop # jeśli nie, następna iteracja
next: # label
cmpl [=10=], %esi # porównaj licznik z 0
jz exit # jeśli koniec, jump exit
decl %esi # esi--
movl , %eax # kod 4 = zapis
movl %esp, %ecx # znak do wypisania
movl , %ebx # domyślny strumień - sys_out
movl , %edx # długość stringa do wypisania?
int [=10=]x80 # przerwanie
addl , %esp #
jmp next # kolejna iteracja
exit:
mov , %eax # zakończenie programu
mov [=10=], %ebx # kod wyjścia
int [=10=]x80 # przerwanie
# ---------------- subprogram ----------------------
input:
movl , %eax # code 3 = input
movl [=10=], %ebx # code 0 = stdin
subl , %esp # move stack pointer by 4 bytes
movl %esp, %ecx # set reading position onto stack
movl , %edx # read 4 bytes
int [=10=]x80 # interrupt to execute above
cmp %esp, '0' # if(input == '0') sum else diff
jz sum
jnz diff
ret
sum:
movl , %eax # pierwsza liczba sumy
movl , %ebx # druga liczba sumy
addl %ebx, %eax # suma, wynik w eax
ret
diff:
movl , %eax # pierwsza liczba sumy
movl , %ebx # druga liczba sumy
subl %ebx, %eax # roznica, wynik w eax
ret
# ------------- end -------------
如何编辑我的 input
函数以读取 character/number 并将其与 0
进行比较?
cmp %esp, '0'
是错误的,因为它试图将 %esp
的值与内存中地址 '0'
的值进行比较。 At&t 语法使用反向操作数,它需要立即数的 $
前缀。但你已经知道这一点,我想你只是有点粗心。正确的指令是 cmpb $'0', (%esp)
将内存中地址 %esp
的字节与地址 0
的 ascii 码进行比较。
此外,您从堆栈中分配了 4 个字节,但您从未释放它。当您最终点击 ret
时,它将使用您的局部变量作为 return 地址,这当然是一件坏事 :) 一个不错的技巧是使用 lea 4(%esp), %esp
释放它而不影响标志,因此您可以在 cmp
和 jz
之间执行此操作。如果你喜欢不那么棘手的东西,你当然可以将输入弹出到寄存器中并在比较中使用它,例如:
pop %eax
cmp $'0', %al
PS:学习使用调试器。那会直接指向你的说明,然后你可能会自己找出问题。
我有一个程序应该根据用户输入 0
或 not 0
添加或减去两个硬编码数字。我在 input
中收到内存访问冲突错误。当我在第 9 行尝试 call sum
或 call diff
而不是 input
时,它工作正常并给出了预期的输出。 loop
和 next
用于显示堆栈的结果。
.text
.global _start
_start:
xorl %esi, %esi # zerowanie licznika
call input # <---- line 9
loop: # label
movl [=10=], %edx # reszta z dzielenia
movl , %ebx # dzielnik
divl %ebx # dzielenie, wynik w eax, reszta w edx
addl , %edx # kod ASCII
pushl %edx # edx na stos
incl %esi # esi++
cmpl [=10=], %eax # porównaj wynik i 0
jz next # jeśli koniec, jump next
jmp loop # jeśli nie, następna iteracja
next: # label
cmpl [=10=], %esi # porównaj licznik z 0
jz exit # jeśli koniec, jump exit
decl %esi # esi--
movl , %eax # kod 4 = zapis
movl %esp, %ecx # znak do wypisania
movl , %ebx # domyślny strumień - sys_out
movl , %edx # długość stringa do wypisania?
int [=10=]x80 # przerwanie
addl , %esp #
jmp next # kolejna iteracja
exit:
mov , %eax # zakończenie programu
mov [=10=], %ebx # kod wyjścia
int [=10=]x80 # przerwanie
# ---------------- subprogram ----------------------
input:
movl , %eax # code 3 = input
movl [=10=], %ebx # code 0 = stdin
subl , %esp # move stack pointer by 4 bytes
movl %esp, %ecx # set reading position onto stack
movl , %edx # read 4 bytes
int [=10=]x80 # interrupt to execute above
cmp %esp, '0' # if(input == '0') sum else diff
jz sum
jnz diff
ret
sum:
movl , %eax # pierwsza liczba sumy
movl , %ebx # druga liczba sumy
addl %ebx, %eax # suma, wynik w eax
ret
diff:
movl , %eax # pierwsza liczba sumy
movl , %ebx # druga liczba sumy
subl %ebx, %eax # roznica, wynik w eax
ret
# ------------- end -------------
如何编辑我的 input
函数以读取 character/number 并将其与 0
进行比较?
cmp %esp, '0'
是错误的,因为它试图将 %esp
的值与内存中地址 '0'
的值进行比较。 At&t 语法使用反向操作数,它需要立即数的 $
前缀。但你已经知道这一点,我想你只是有点粗心。正确的指令是 cmpb $'0', (%esp)
将内存中地址 %esp
的字节与地址 0
的 ascii 码进行比较。
此外,您从堆栈中分配了 4 个字节,但您从未释放它。当您最终点击 ret
时,它将使用您的局部变量作为 return 地址,这当然是一件坏事 :) 一个不错的技巧是使用 lea 4(%esp), %esp
释放它而不影响标志,因此您可以在 cmp
和 jz
之间执行此操作。如果你喜欢不那么棘手的东西,你当然可以将输入弹出到寄存器中并在比较中使用它,例如:
pop %eax
cmp $'0', %al
PS:学习使用调试器。那会直接指向你的说明,然后你可能会自己找出问题。