From what I understand, when a parameter is passed in a function call in C, the callee can find the first parameter at [ebp+8]
.
Returning a value through eax
works for me, reading the right parameter value from the stack doesn't.
根据我所理解的,当一个参数在C中的函数调用中传递时,callee可以在[ebp+8]中找到第一个参数。通过eax返回一个值为我工作,从堆栈中读取正确的参数值不会。
Right now I'm just trying to write an assembly function, that can be called from C and returns the same value, that it is being passed.
现在,我只是尝试编写一个程序集函数,它可以从C调用,并返回相同的值,它正在被传递。
When I run the following program, it prints number: 1
to the console, no matter what value is passed into myFunc
. What am I doing wrong?
当我运行下面的程序时,它会输出数字:1到控制台,无论什么值被传递到myFunc。我做错了什么?
assembly.s
assembly.s
section .text
global _myFunc
_myFunc:
mov eax, [ebp+8]
ret
main.c
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;
}
I'm using a Mac, nasm to assemble the code and gcc for C compilation.
我正在使用一个Mac, nasm来汇编代码和gcc来进行C编译。
Makefile
Makefile
macho32:
nasm -f macho32 assembly.s
gcc -m32 -o macho32 assembly.o main.c
3 个解决方案
#1
1
you refer to argument on stack, by reading from [EBP+offset] - has EBP been set up to actually point at stack? If no, you may have to do that first, conventionally done by:
您引用了堆栈上的参数,通过读取[EBP+偏移量]——是否设置了EBP来实际指向堆栈?如果没有,你可能必须先做,传统的做法:
push ebp
mov ebp,esp
Only then points EBP to its stacked previous contents, below stacked return address, and below passed arguments.
只有这样,EBP才会在堆叠的返回地址下面,并在下面传递参数。
#2
1
You need to setup to access the the parameters first by saving esp
. This is explained in:
您需要设置先通过保存esp来访问这些参数。
http://www.nasm.us/doc/nasmdoc9.html
http://www.nasm.us/doc/nasmdoc9.html
in section "9.1.2 Function Definitions and Function Calls"
在“9.1.2函数定义和函数调用”一节中
The following works for me
以下是我的工作。
assembly.s
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
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;
}
Assembly & Compilation
装配和编译
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
I am on a linux machine so I use elf32
. The use of macho32
is correct on your Mac.
我在一台linux机器上,所以我使用elf32。macho32的使用在你的Mac电脑上是正确的。
#3
1
Your function should look like this,
函数应该是这样的,
_myFunc:
push ebp ; setup ebp as frame pointer
mov ebp, esp
mov eax, [ebp + 8]
leave ; mov esp,ebp / pop ebp
ret
The convention is to use ebp to access the parameters, to do so you need to save ebp on the stack and make it to point to the new top of the stack. At function exit you should restore ebp and esp, as the leave instruction does.
该约定是使用ebp访问参数,这样就需要将ebp保存在堆栈上,并使其指向堆栈的新顶部。在功能退出时,您应该恢复ebp和esp,就像leave指令所做的那样。
In nasm there is a macro package, c32.mak, that can help in supporting the C calling convention, these macros are arg, proc and endproc. Using these macros your code should look like,
在nasm中有一个宏包c32。mak可以帮助支持C调用约定,这些宏是arg、proc和endproc。使用这些宏代码应该是这样的,
proc _myfunc
%$i arg
mov eax, [ebp + %$i]
endproc
#1
1
you refer to argument on stack, by reading from [EBP+offset] - has EBP been set up to actually point at stack? If no, you may have to do that first, conventionally done by:
您引用了堆栈上的参数,通过读取[EBP+偏移量]——是否设置了EBP来实际指向堆栈?如果没有,你可能必须先做,传统的做法:
push ebp
mov ebp,esp
Only then points EBP to its stacked previous contents, below stacked return address, and below passed arguments.
只有这样,EBP才会在堆叠的返回地址下面,并在下面传递参数。
#2
1
You need to setup to access the the parameters first by saving esp
. This is explained in:
您需要设置先通过保存esp来访问这些参数。
http://www.nasm.us/doc/nasmdoc9.html
http://www.nasm.us/doc/nasmdoc9.html
in section "9.1.2 Function Definitions and Function Calls"
在“9.1.2函数定义和函数调用”一节中
The following works for me
以下是我的工作。
assembly.s
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
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;
}
Assembly & Compilation
装配和编译
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
I am on a linux machine so I use elf32
. The use of macho32
is correct on your Mac.
我在一台linux机器上,所以我使用elf32。macho32的使用在你的Mac电脑上是正确的。
#3
1
Your function should look like this,
函数应该是这样的,
_myFunc:
push ebp ; setup ebp as frame pointer
mov ebp, esp
mov eax, [ebp + 8]
leave ; mov esp,ebp / pop ebp
ret
The convention is to use ebp to access the parameters, to do so you need to save ebp on the stack and make it to point to the new top of the stack. At function exit you should restore ebp and esp, as the leave instruction does.
该约定是使用ebp访问参数,这样就需要将ebp保存在堆栈上,并使其指向堆栈的新顶部。在功能退出时,您应该恢复ebp和esp,就像leave指令所做的那样。
In nasm there is a macro package, c32.mak, that can help in supporting the C calling convention, these macros are arg, proc and endproc. Using these macros your code should look like,
在nasm中有一个宏包c32。mak可以帮助支持C调用约定,这些宏是arg、proc和endproc。使用这些宏代码应该是这样的,
proc _myfunc
%$i arg
mov eax, [ebp + %$i]
endproc