linking NASM code with gcc code

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
elias

linking NASM code with gcc code

Post by elias »

if i write a function in NASM, then compile it to object code, how would i call it from my c object code? is there a specific way to write thte function in NASM so that it links with gcc? i hate gcc assembly and want to use NASM for all ym assembly needs
jrfritz

Re:linking NASM code with gcc code

Post by jrfritz »

If using c code this:

in your c module:

extern function();

<you can use your function in your code somewhere now>

in your asm module:

; if using windows replace function with _function
global function

function:

<code>

ret

That help?
elias

Re:linking NASM code with gcc code

Post by elias »

that simple? thanx
Schol-R-LEA

Re:linking NASM code with gcc code

Post by Schol-R-LEA »

While that wouls allow you call the functions, as a practical matter, there are a few other issues to be aware of, mostly involving saving registers, and the passing of arguments and return values.

Specifically, gcc requires you to preserve all registers except EAX, EDX, EFLAGS, FS and GS. The stack pointer and base pointer are particularly important to preserve correctly, as they are necessary for restoring the calling function's state. As a general rule, the first thing an assembly function should do when called from C is to push the existing EBP, then copy the current stack pointer to the EBP, so as to set up the stack frame; then any of the other sacred registers which the function used should be pushed as well. For example:

Code: Select all

global foo

foo:
   push EBP
   mov EAX, ESP
   mov EBP, EAX
   push EDI
   push ESI
Arguments are passed on the stack, just before the function call is made, in reverse order from how they appear in the C function call. Thus, the call

Code: Select all

int foo (int bar, char quux)

foo(23, 'w')
would push 77 00 00 00, then 17 00 00 00, then the address of the calling function. In case you were puzzled, gcc always uses 32-bit argument size stack segments, and values are pushed in little-endian order. These value are in hex, of course (those who point out that 23dec == 17hex will be assumed to be eligible for immediate ordination as Deacons in the LDD for mentioning it, and referred to in the appropriate manner).

To access the arguments, you need to index them from the EBP, so that to copy the value of bar into EAX, you would use

Code: Select all

mov EAX, [EBP + 8]   ; add 4 for the old EBP, and another 4 for the caller's return address
Finally, return arguments are passed through thr EAX and EDX registers, with arguments larger than 8 bytes passed implicitly by a pointer.

For more details, see the DJGPP FAQ page regarding mixing C and assembly code (it is not specific to DJGPP, however). HTH. CCW.
Post Reply