Assembly: Passing Values From C

Programming, for all ages and all languages.
Post Reply
User avatar
Octacone
Member
Member
Posts: 1138
Joined: Fri Aug 07, 2015 6:13 am

Assembly: Passing Values From C

Post by Octacone »

I need some quick help.
How do I do this:

Code: Select all

C code:
void MyFunction(void* test1, void* test2, size_t size)
{
     MyFunctionDoAssembly(test1, test2, size);
}
NASM Code:
MyFunctionDoAssembly:
    mov test1, esi
    mov test2, edi
    mov size, ebx
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
Octocontrabass
Member
Member
Posts: 5513
Joined: Mon Mar 25, 2013 7:01 pm

Re: Assembly: Passing Values From C

Post by Octocontrabass »

Somewhere in your C code you'll need a function declaration. (Usually, this will go in one of your .h files.)

Code: Select all

void MyFunction(void* test1, void* test2, size_t size);
In your assembly code, you'll need to appropriately declare the function.

Code: Select all

global MyFunction

section .text
MyFunction:
    ;your code here
The name you need to use in your assembly code depends on your ABI, but the most common ABIs use the same name in both assembly and C. GCC has some helpful function attributes that you can use to change the ABI, in case the defaults are inconvenient.
User avatar
MichaelFarthing
Member
Member
Posts: 167
Joined: Thu Mar 10, 2016 7:35 am
Location: Lancaster, England, Disunited Kingdom

Re: Assembly: Passing Values From C

Post by MichaelFarthing »

octacone wrote:I need some quick help.
How do I do this:

Code: Select all

C code:
void MyFunction(void* test1, void* test2, size_t size)
{
     MyFunctionDoAssembly(test1, test2, size);
}
NASM Code:
MyFunctionDoAssembly:
    mov test1, esi
    mov test2, edi
    mov size, ebx
I am assuming you are asking about how to get at the location of the variables test1, test2 etc.
Forgive me if I seem to be teaching you to suck eggs, but if you haven't worked at assembly level before you may not know some of this.

Firstly, you must know how yor C code will carry out the calling of "MyFunctionDoAssembly", called the 'calling convention'

Traditional C put size, test2, and test1 onto the stack and then did a call instruction. This is called the C calling convention and note that the parameters go on to the stack from the end i.e. backwards. There are good reasons for doing this, principally to allow C to implement functions with varying numbers of parameters, like printf, but that doesn't need to be explained in detail here. Another issue is whether the caller or the called function 'cleans up the stack' at the end of the call. An advantage of the C calling convention from your point of view is that the caller is responsible, so your assembler function doesn't have to worry about that

An alternative method is to use the Pascal or Standard calling conventions in which the parameters are put on the stack forwards, or a register calling convention where the parameters don't go on to the stack at all and are passed in registers.

To be sure what happens you should declare your functions with an explicit calling convention and I'm using the C convention as an example here: "_cdecl void MyFunctionDoAssembly

The start of your function can then be like this:

push ebp ;Save ebp so the calling routine gets it back in tact
mov ebp esp ;ebp now provides a stable pointer into the stack

The stack (working upwards from what ebp points to) now looks this this


ebp -> Currently the value of esp, but esp may alter during your routine
[ebp+4] Old value of ebp that you have just pushed
[ebp+8] Return address for getting back to the calling function
[ebp+12] *test1 [Lowest in memory, pushed on to the stack most recently]
[ebp+16] *test2
[ebp+20] size4 [Highest in memory, pushed on to the stack first by the caller]

so mov test1,esi is coded mov [ebp+12], esi

{{EDIT}}

Whoops! What a load of rubbish
[ebp+12] is of course a pointer to your real object so you will almost certainly require something like:

mov ebx [ebp+12]
mov [ebx] esi

or, if test1 is a structure:

mov [ebx+someoffset] esi

{{End edit}}

and when you've finished:

pop ebp
ret

Caveats
-----------

Don't know where you're writing your assembler function. If, for example, you are using inbuilt facilities within your compiler it may do some of this work for you and so you should not duplicate it. If your using a separate assembler, then it will also have conventions you can use to simplify all this. I've also assumed you're using a flat 32 bit model.
User avatar
Ycep
Member
Member
Posts: 401
Joined: Mon Dec 28, 2015 11:11 am

Re: Assembly: Passing Values From C

Post by Ycep »

Exactly.
User avatar
Octacone
Member
Member
Posts: 1138
Joined: Fri Aug 07, 2015 6:13 am

Re: Assembly: Passing Values From C

Post by Octacone »

Octocontrabass wrote:reply
MichaelFarthing wrote:reply
Thank you guys. That is what I was looking for.
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
Post Reply