I have this simple C source code :
#include <stdio.h>
extern int Sum(int,int);
int main()
{
int a,b,s;
a=1 , b=2;
s = Sum(a,b);
return 0;
}
and i have this s.asm which defines the function _Sum :
global _Sum
_Sum:
push ebp ; create stack frame
mov ebp, esp
mov eax, [ebp+8] ; grab the first argument
mov ecx, [ebp+12] ; grab the second argument
add eax, ecx ; sum the arguments
pop ebp ; restore the base pointer
ret
now , i compiled the .asm using :
nasm s.asm -f elf -o s.o
and compiled and linked the .c file using :
gcc s.o test.o -o testapp
this is the outcome :
/tmp/ccpwYHDQ.o: In function `main':
test.c:(.text+0x29): undefined reference to `Sum'
collect2: ld returned 1 exit status
So what is the problem ?
I'm using Ubuntu-Linux
Any help would be greatly appreciated , Thanks
[SOLVED] : i checked with nm the test.o file and it expected to find the symbol 'Sum' not '_Sum' so changing that solved the problem.
In typical assemblers, labels are by default local. To tell the assembler to make them visible to external routines, you must add a declaration, such as:
.globl _Sum
Additionally, declare the routine correctly in C. This is not the cause of your link error but can cause other problems:
extern int Sum(int, int);
For completeness, with thanks to the commenters: Do not overwrite your object files. You can assemble, compile, and link with:
nasm s.asm -f elf -o s.o
gcc test.c s.o -o test
(This names the executable “test”, and you will probably have to execute it with “./test” to distinguish the “test” in your directory from the “test” command. You may be happier choosing another name.)
For educational purposes: If you have the nm
tool on your system, execute the command nm so
. It may show you something like:
00000000 t _Sum
The t
means that _Sum
is a local label in the code section. (The code section is also called the text section, hence the t.) Once you add the .globl
declaration and assemble the new source, nm so
should show you an uppercase T
instead. Uppercase indicates the label is externally visible.
As far as I can see from your question, you overwrite your object file that came from the assembler so
by the C program. So you don't have the assembler routine any more.
You should probably write
Generate the so
object file
nasm s.asm -f elf -o s.o
Generate the test.o
(your command created another so)
gcc test.c -c
Link the app
gcc s.o test.o -o testapp
(I chose testapp as output binary because test
is often a very bad name for a program, it collides with the Unix command test
)
It is better to declare the asm inline in c files. Here is an example from my own code:
bool KxMutex::tryLock_i()
{
#ifdef KX_MUTEX_ASM
int oldLock;
#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
asm volatile (
"movl $1,%%eax\n\t"
"xchg %%eax,%0\n\t"
"movl %%eax,%1\n\t"
: "=m" (mLock), "=m" (oldLock)
:
: "%eax", "memory"
);
#elif defined(__GNUC__) && (defined(__ppc__))
int newLock = 1;
asm volatile (
"\n1:\n\t"
"lwarx %0,0,%1\n\t"
"cmpwi 0,%0,0\n\t"
"bne- 2f\n\t"
"stwcx. %2,0,%1\n\t"
"bne- 1b\n\t"
"isync\n"
"2:\n\t"
: "=&r" (oldLock)
: "r" (&mLock), "r" (newLock)
: "cr0", "memory"
);
#endif
return ( oldLock == 0 );
#else // !KX_MUTEX_ASM
return ( pthread_mutex_trylock( (pthread_mutex_t*)this ) ? false : true );
#endif // !KX_MUTEX_ASM
}
There are many advantages:
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.