根据我的理解,当在C中的函数调用中传递参数时,被调用者可以在[ebp+8]
找到第一个参数。
通过eax
返回值对我有用,从堆栈中读取正确的参数值不会。
现在我只是尝试编写一个汇编函数,可以从C调用并返回相同的值,即传递它。
当我运行以下程序时,无论将什么值传递到number: 1
,它都会向控制台输出myFunc
。我做错了什么?
assembly.s
section .text
global _myFunc
_myFunc:
mov eax, [ebp+8]
ret
的main.c
#include <stdio.h>
extern unsigned int myFunc(unsigned int somedata);
int main() {
unsigned int i = myFunc(6);
printf("number: %i\n",i);
return 0;
}
我使用Mac,nasm来汇编代码和gcc进行C编译。
生成文件
macho32:
nasm -f macho32 assembly.s
gcc -m32 -o macho32 assembly.o main.c
答案 0 :(得分:1)
你在堆栈上引用参数,通过读取[EBP + offset] - EBP是否设置为实际指向堆栈?如果不是,您可能必须先执行此操作,通常由以下方式完成:
push ebp
mov ebp,esp
然后才将EBP指向其堆叠的先前内容,低于堆叠的返回地址,以及下面传递的参数。
答案 1 :(得分:1)
您需要设置以首先保存esp
来访问参数。这在下面解释:
http://www.nasm.us/doc/nasmdoc9.html
在“9.1.2函数定义和函数调用”一节中
以下为我工作
assembly.s
section .text
global myFunc:function
myFunc:
push ebp
mov ebp, esp
mov eax, [ebp+8]
mov esp, ebp
pop ebp
ret
的main.c
#include <stdio.h>
extern unsigned int myFunc(unsigned int somedata);
int main() {
unsigned int i = myFunc(6);
printf("number: %i\n",i);
return 0;
}
装配&amp;汇编
ericu@eric-phenom-linux:~$ nasm -f elf32 assembly.s
ericu@eric-phenom-linux:~$ gcc -m32 assembly.o main.c
ericu@eric-phenom-linux:~$ ./a.out
number: 6
我在linux机器上,所以我使用elf32
。在Mac上使用macho32
是正确的。
答案 2 :(得分:1)
你的功能应该是这样的,
_myFunc:
push ebp ; setup ebp as frame pointer
mov ebp, esp
mov eax, [ebp + 8]
leave ; mov esp,ebp / pop ebp
ret
惯例是使用 ebp 来访问参数,为此你需要在堆栈上保存 ebp 并使其指向新的顶部堆。在功能退出时,你应该恢复 ebp 和 esp ,因为离开指令。
在 nasm 中有一个宏包 c32.mak ,可以帮助支持 C调用约定,这些宏是< strong> arg , proc 和 endproc 。 使用这些宏,您的代码应该是,
proc _myfunc
%$i arg
mov eax, [ebp + %$i]
endproc