[英]Calling assembly routines from C source code
I have this simple C source code :我有这个简单的 C 源代码:
#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 :我有这个 s.asm 定义函数 _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 :现在,我编译了 .asm 使用:
nasm s.asm -f elf -o s.o
and compiled and linked the .c file using :并使用以下命令编译和链接 .c 文件:
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我正在使用 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. [已解决]:我用 nm 检查了 test.o 文件,它希望找到符号“Sum”而不是“_Sum”,因此更改解决了问题。
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:此外,在 C 中正确声明例程。这不是链接错误的原因,但可能会导致其他问题:
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.) (这将可执行文件命名为“test”,您可能必须使用“./test”来执行它,以将目录中的“test”与“test”命令区分开来。您可能更愿意选择其他名称。)
For educational purposes: If you have the nm
tool on your system, execute the command nm so
.出于教育目的:如果您的系统上有nm
工具,请执行命令nm so
。 It may show you something like:它可能会显示如下内容:
00000000 t _Sum
The t
means that _Sum
is a local label in the code section. t
表示_Sum
是代码部分中的本地标签。 (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. (代码部分也称为文本部分,因此称为 t。)一旦您添加了.globl
声明并组装了新的源代码, nm so
应该向您显示一个大写的T
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
被 C 程序覆盖。 So you don't have the assembler routine any more.所以你不再有汇编程序了。
You should probably write你应该写
Generate the so
object file生成so
对象文件
nasm s.asm -f elf -o s.o
Generate the test.o
(your command created another so)生成test.o
(您的命令创建了另一个 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
) (我选择 testapp 作为输出二进制文件,因为test
通常是一个非常糟糕的程序名称,它与 Unix 命令test
冲突)
It is better to declare the asm inline in c files.最好在 c 文件中声明 asm inline。 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:有很多优点:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.