禁止非法指示

时间:2013-04-12 17:51:53

标签: c function assembly x86 nasm

我正在使用一个项目来实现在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

1 个答案:

答案 0 :(得分:3)

mov esp, ebp更改esp以指向mov ebp, esp执行时的位置。那是在您将esiediebx推入堆栈之前,因此您无法再将其弹出。既然如此,堆栈是错误的,ret无法正常工作。

您可以删除mov esp, ebp指令。只有在例程中对堆栈指针进行了可变更改(例如,将堆栈移动到所需的对齐或为可变长度数组腾出空间)时,才需要像这样恢复堆栈指针。如果您的堆栈处理简单,那么您只需按照推送的顺序弹出。如果您对堆栈进行了可变更改,则需要将指针还原到其他位置,而不是已保存的ebp,以便您可以弹出ebxedi,和esi