基于用户输入的汇编调用子程序 [英] Assembly call subprograms based on user input

查看:122
本文介绍了基于用户输入的汇编调用子程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个程序,应该根据用户输入0not 0来添加或减去两个硬编码数字.我在input中收到内存访问冲突错误.当我尝试在第9行中使用call sumcall diff代替input时,它工作正常,并为我提供了预期的输出. loopnext用于显示堆栈结果.

I have a program that is supposed to either add or subtract two hardcoded numbers based on user input 0 or not 0. I get memory access violation error inside input. when i try to call sum or call diff instead input in line 9 it works fine and gives me expected output. loop and next is used to display result from stack.

.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    -------------

如何编辑input函数以读取字符/数字并将其与0进行比较?

How can I edit my input function to read a character/number and compare it to 0?

推荐答案

cmp %esp, '0'是错误的,因为它试图将%esp的值与内存中位于地址'0'的值进行比较. At& t语法使用相反的操作数,并且需要$前缀作为立即数.但是您已经知道这一点,我想您只是有些粗心.正确的指令是cmpb $'0', (%esp),用于将地址%esp中的内存字节与0的ASCII码进行比较.

cmp %esp, '0' is wrong, because it tries to compare the value of %esp to the value in memory at address '0'. At&t syntax uses reversed operands, and it needs a $ prefix for immediates. But you already know this, I guess you were just a little careless. The correct instruction is cmpb $'0', (%esp) to compare the byte in memory at address %esp to the ascii code of 0.

此外,您从堆栈中分配了4个字节,但从未释放过该字节.当您最终命中ret时,它将使用您的局部变量作为返回地址,这当然是一件坏事:)一个不错的技巧是使用lea 4(%esp), %esp释放它而不影响标志,因此您可以在cmpjz.如果您不喜欢复杂的东西,当然可以将输入弹出到寄存器中,并在比较中使用它,例如:

Furthermore, you allocated 4 bytes from the stack, but you never free that. When you eventually hit a ret it will use your local variable as return address which is of course a bad thing :) A nice trick is to use lea 4(%esp), %esp to free it without affecting the flags, so you can do this between the cmp and the jz. If you like less tricky stuff, you can of course just pop the input into a register and use that in the comparison, such as:

pop %eax
cmp $'0', %al

PS:学习使用调试器.那将直接把您指向该指令,然后您可能会自己找出问题所在.

PS: Learn to use a debugger. That would have pointed you directly at the instruction, and then you probably could have figured out the problem yourself.

这篇关于基于用户输入的汇编调用子程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆