不能将参数从C传递到汇编代码?

时间:2021-08-06 13:50:06

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