Page 1 of 1

Calling Assembly (nasm) from C (GCC on linux)

Posted: Wed Jan 14, 2004 12:00 am
by gablooky
I'm new to this whole lark (OS dev), and I've hit on a little snag.

I want to be able to call an assembly function (done in nasm) from my C kernel code (compiled with GCC on linux).

As I understand it, I can do something like this:

//------ main.c
#include <stdio.h>

extern int Add(int,int);

int main()
{
    int x;
    x = Add(2,2); // should be 4...
    printf("2+2=%d\n",x);
}

//--------Add.asm
[BITS 32]

GLOBAL _Add

SECTION .text
_Add:
    push ebp
    mov ebp,esp
    mov eax,[ebp+8]
    mov ecx,[ebp+12]
    add eax,ecx
    pop ebp
    ret

And I compile this with:
    nasm -f aout Add.asm
    gcc -c main.c
    gcc Add.o main.o

But I get an 'undefined reference in function main' error when linking.

I know it's probably something simple, but can anyone help me out or point me the right direction? It'd be much appreciated.

RE:Calling Assembly (nasm) from C (GCC on linux)

Posted: Wed Jan 14, 2004 12:00 am
by gablooky
I should also point out I'm using the code from here:
http://courses.ece.uiuc.edu/ece291/book ... ixing.html

RE:Calling Assembly (nasm) from C (GCC on linux)

Posted: Thu Jan 15, 2004 12:00 am
by mikeleany
Everything looks okay to me (assuming a.out is the default output for gcc on your machine). An undefined reference to main shouldn't have anything to do with your Add function anyway. If I were you, I would just start with what you've posted (nothing more), and start gradually taking stuff out, until it compiles (in which case you've found the problem) or you end up with just this

int main()
{
}

and it still doesn't compile (quite unlikely), in which case, something must be really messed up.

RE:Calling Assembly (nasm) from C (GCC on linux)

Posted: Fri Jan 16, 2004 12:00 am
by gablooky
I figured it out. It should be this:

//------ main.c
#include <stdio.h>

int Add(int,int) __attribute__((cdecl));

int main()
{
    int x;
    x = Add(2,2); // should be 4...
    printf("2+2=%d\n",x);
    return 0;
}

//--------Add.asm
[BITS 32]

GLOBAL Add

SECTION .text
Add:
    push ebp
    mov ebp,esp
    mov eax,[ebp+8]
    mov ecx,[ebp+12]
    add eax,ecx
    pop ebp
    ret

And I compile this with:
    nasm -f aout Add.asm // elf also works
    gcc -c main.c
    gcc Add.o main.o

It was the __attribute__ in the c file, and the underscored labels in the assembly. Gak. One of those things.

RE:Calling Assembly (nasm) from C (GCC on linux)

Posted: Fri Jan 16, 2004 12:00 am
by carbonBased
That __attribute__ is GCC specific, just so you know.

extern int Add(int, int);

should have worked, as well (and have been portable).

Just to note; the underscores are used in most binary specifications (ie, MX EXE, COFF, etc), but is not used in ELF.  So, if you plan on keeping all your code as ELF, this solution is perfect.

If, however, you _might_ be working with different binary formats, you might want to look into some preprocessor defines, etc, in order to take care of this "floating underscore" issue :)

Just an FYI.

Cheers,
Jeff