我正在使用一个项目来实现在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
答案 0 :(得分:3)
mov esp, ebp
更改esp
以指向mov ebp, esp
执行时的位置。那是在您将esi
,edi
和ebx
推入堆栈之前,因此您无法再将其弹出。既然如此,堆栈是错误的,ret
无法正常工作。
您可以删除mov esp, ebp
指令。只有在例程中对堆栈指针进行了可变更改(例如,将堆栈移动到所需的对齐或为可变长度数组腾出空间)时,才需要像这样恢复堆栈指针。如果您的堆栈处理简单,那么您只需按照推送的顺序弹出。如果您对堆栈进行了可变更改,则需要将指针还原到其他位置,而不是已保存的ebp
,以便您可以弹出ebx
,edi
,和esi
。