1

我正在处理一个在 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
4

1 回答 1

4

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

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

于 2013-04-12T18:01:06.233 回答