Tim Bodeit
Tim Bodeit

Reputation: 9703

Can't pass parameter from C to Assembly code

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.

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.

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?


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;
}

I'm using a Mac, nasm to assemble the code and gcc for C compilation.

Makefile

macho32:
    nasm -f macho32 assembly.s
    gcc -m32 -o macho32 assembly.o main.c

Upvotes: 0

Views: 1793

Answers (3)

xae
xae

Reputation: 181

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.

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,

proc _myfunc
%$i arg

    mov     eax, [ebp + %$i]

endproc

Upvotes: 1

Eric Urban
Eric Urban

Reputation: 3820

You need to setup to access the the parameters first by saving esp. This is explained in:

http://www.nasm.us/doc/nasmdoc9.html

in section "9.1.2 Function Definitions and Function Calls"

The following works for me

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;
}

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.

Upvotes: 2

Deleted User
Deleted User

Reputation: 2541

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:

push  ebp    
mov   ebp,esp

Only then points EBP to its stacked previous contents, below stacked return address, and below passed arguments.

Upvotes: 1

Related Questions