【问题标题】:x86 assembly recursive function -> Illegal instruction errorx86 汇编递归函数 -> 非法指令错误
【发布时间】:2015-05-09 18:18:52
【问题描述】:

Code1:实现调用fact(阶乘)函数的main函数

section .data
    msg db "Enter the Number whose factorial is to be calculated",10,0
    msg1 db "The factorial is: ",0
    ioput db "%d"

section .bss
    a resd 1

section .text
    global main
    extern printf,scanf,fact
main:   
    pusha 
    push msg
    call printf
    add esp,4
    popa

    pusha 
    push a
    push ioput
    call scanf
    add esp,8
    popa

    mov ebx,dword[a]

    pusha
    push ebx
    call fact
    add esp,4


    pusha
    push msg1
    call printf
    add esp,4
    popa

    pusha
    push eax
    push ioput
    call printf
    add esp,8
    popa

    ret

实现事实(阶乘函数)的代码2:

section .text
    global fact
    extern printf,scanf
fact:   
    enter 0,0
    cmp ebx,1
    jnz next
    ret

next:
    push ebx
    dec ebx
    call fact
    pop ebx
    mul eax,ebx
    leave
    ret

系统统计:32 位机器,Ubuntu 14.04,使用 Nasm

问题说明:程序收到信号SIGILL,指令非法。为什么会出现此错误?

【问题讨论】:

  • pushapopa 甚至不平衡。检查包含call fact 的块。以这种方式返回会去一个有趣的地方。
  • 另外,学习使用调试器。

标签: assembly x86 nasm


【解决方案1】:
mov ebx,dword[a]

pusha
push ebx
call fact
add esp,4

这是您的程序有一些问题的部分!

  1. 您需要初始化 EAX 以通过调用 fact 获得有意义的结果。一个方便的数字是 1。
  2. 由于您使用了pusha,因此您还需要使用popa。我宁愿没有,因为您的代码并不真正需要它。
  3. fact 例程不使用堆栈上传递的参数。它只是为此目的使用 EBX 寄存器。这意味着您可以省略push ebxadd esp,4,也可以从fact 中删除enterleave 指令。

这是您可以编写的代码来解决所有问题。

mov ebx,dword[a]
mov eax,1
pusha
call fact
mov [esp+28],eax
popa

一个较短的版本是

mov ebx,dword[a]
mov eax,1
call fact

【讨论】:

  • 谢谢!但我不明白你为什么这样做:mov [esp+28],eax
  • 如果没有这条指令,popa 将用pusha 保存的 EAX 值替换 EAX 中 fact 的结果。偏移量 +28 是 pusha 存储 EAX 的确切位置。
猜你喜欢
  • 1970-01-01
  • 2013-08-11
  • 2015-06-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-18
  • 2017-10-23
相关资源
最近更新 更多