【问题标题】:Ret illegal instructionret非法指令
【发布时间】:2013-04-05 08:40:34
【问题描述】:

我正在处理一个在程序集中实现一个在 main.c 中调用的函数的项目。 C 中的签名函数声明是void strrev(char *str) ; Ret 指令给了我一个非法指令错误。为什么?这是我第一次这样做。

尝试只发布相关代码:

SECTION .text
        global strrev

strrev:
        push    ebp
        mov     ebp, esp

        push    esi
        push    edi
        push    ebx

// doing things with al, bl, ecx, edi, and esi registers here


// restore registers and return    
        mov     esp,    ebp
        pop     ebx
        pop     edi
        pop     esi
        pop     ebp

        ret

错误:

(gdb)
Program received signal SIGILL, Illegal instruction.
0xbffff49a in ?? ()

以这种方式编译和链接:

nasm -f elf -g strrepl.asm
nasm -f elf -g strrev.asm
gcc -Wall -g -c main7.c
gcc -Wall -g strrepl.o strrev.o main7.o

【问题讨论】:

  • 仔细观察调试器中弹出的内容以及返回的位置。

标签: c function assembly x86 nasm


【解决方案1】:

mov esp, ebp 更改 esp 以指向执行 mov ebp, esp 时的位置。那是在您将esi、edi 和ebx 压入堆栈之前,因此您不能再将它们弹出。既然你这样做了,堆栈是错误的,ret 不能按预期工作。

您可以删除mov esp, ebp 指令。仅当您在例程中对堆栈指针进行了可变更改(例如,将堆栈移动到所需的对齐方式或为可变长度数组腾出空间)时,才需要像这样恢复堆栈指针。如果您的堆栈被简单地处理,那么您只需按照您推送的相反顺序弹出。如果您确实对堆栈进行了变量更改,那么您需要将指针恢复到不同的位置,而不是您保存的ebp,以便您可以弹出ebx、edi和esi。

【讨论】:

  • 明白了,我认为是有道理的。我回家后会进一步研究。
  • 现在它通过了返回,但是当 main.c 程序去打印我反转的字符串时,它打印了空字符串
猜你喜欢
  • 2017-09-04
  • 2012-12-15
  • 2018-11-01
  • 2018-04-30
  • 1970-01-01
  • 1970-01-01
  • 2013-12-06
  • 2019-01-20
  • 2021-02-01
相关资源
最近更新 更多