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

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
gablooky

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

Post 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.
gablooky

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

Post by gablooky »

I should also point out I'm using the code from here:
http://courses.ece.uiuc.edu/ece291/book ... ixing.html
mikeleany

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

Post 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.
gablooky

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

Post 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.
carbonBased

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

Post 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
Post Reply