【问题标题】:Assembly call subprograms based on user input基于用户输入的汇编调用子程序
【发布时间】:2015-03-12 12:50:23
【问题描述】:

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

.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 进行比较?

【问题讨论】:

    标签: linux assembly input x86 att


    【解决方案1】:

    cmp %esp, '0' 是错误的,因为它试图将%esp 的值与内存中地址'0' 的值进行比较。 At&t 语法使用反向操作数,并且它需要一个 $ 前缀来表示立即数。但是你已经知道了,我猜你只是有点粗心。正确的指令是cmpb $'0', (%esp),用于将内存中地址%esp 的字节与0 的ascii 代码进行比较。

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

    pop %eax
    cmp $'0', %al
    

    PS:学习使用调试器。那会直接将您指向说明,然后您可能自己就可以找出问题所在。

    【讨论】:

      猜你喜欢
      • 2012-10-23
      • 2011-01-14
      • 2018-11-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-05
      • 1970-01-01
      相关资源
      最近更新 更多