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.
Calling Assembly (nasm) from C (GCC on linux)
RE:Calling Assembly (nasm) from C (GCC on linux)
I should also point out I'm using the code from here:
http://courses.ece.uiuc.edu/ece291/book ... ixing.html
http://courses.ece.uiuc.edu/ece291/book ... ixing.html
RE:Calling Assembly (nasm) from C (GCC on linux)
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.
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)
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.
//------ 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)
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
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