我非常擅长C,而不是组装,但出于兴趣,我想让一些人在C中使用gcc。问题是我的程序要么提供一些愚蠢的数字或崩溃。
unsigned sadd32(unsigned a, unsigned b)
{
unsigned c = 0;
__asm__("movl %%eax, %0" : "=a"(a));
__asm__("addl %%eax, %0" : "=b"(b));
__asm__("movl %edx, 0xffffffff");
__asm__("cmovc %eax, %edx");
__asm__("movl %0, %%eax" : "=c"(c));
return c;
}
我确定我做过傻事,如果这对任何人都很明显? ;)
答案 0 :(得分:2)
#include <stdio.h>
#include <stdlib.h>
unsigned sadd32(unsigned a, unsigned b)
{
unsigned c = 0;
__asm__ ("movl %2, %%eax\n\t"
"addl %1, %%eax\n\t"
"movl %%eax, %0\n\t"
:"=r"(c)
:"r"(a),"r"(b)
:"%eax"
);
return c;
}
int main()
{
unsigned int a=3,b=5;
printf("The sum of %u and %u is %u\n",a,b,sadd32(a,b));
return 0;
}
参考:http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html
从我看到的,你的代码有一些缺陷::
unsigned sadd32(unsigned a, unsigned b)
{
unsigned c = 0;
__asm__("movl %%eax, %0" : "=a"(a));
__asm__("addl %%eax, %0" : "=b"(b));
__asm__("movl %edx, 0xffffffff"); /* this here, you are specifying a manual location, may not be accessible or valid */
__asm__("cmovc %eax, %edx"); /* resulting in its error */
__asm__("movl %0, %%eax" : "=c"(c));
return c;
}
另外,我相信你不理解“= $”的概念。从我看到的,你只是在那里写变量名,但这不是它的工作原理。从现场,约束限制(如已知),如下:
m’
constraint but not the
o'约束的东西。 有关更多示例和其他限制,请参阅网站。希望这有帮助! :)
答案 1 :(得分:1)
修改:代码已更正,因为迈克尔评论说这是饱和添加。
关于如何使用gcc内联汇编的要点:
asm(
... )
块中。mov
设置内联汇编块开头的值,只需定义输入。以下是代码:
#include <stdio.h>
unsigned my_sadd(unsigned a, unsigned b)
{
asm(
"addl %2, %0;"
"cmovcl %3, %0;"
/* outputs */
: "=r"(a)
/* inputs */
: "0"(a), "r"(b), "r" (0xffffffff)
);
return a;
}
int main(void)
{
unsigned a;
unsigned b;
unsigned c;
a = 123456;
b = 314159;
c = my_sadd(a, b);
printf("%u + %u = %u\n", a, b, c);
a = 0x80000000;
b = 0xF0000000;
c = my_sadd(a, b);
printf("%u + %u = %u\n", a, b, c);
return 0;
}
答案 2 :(得分:1)
除了使用单__asm__
'指令'和AT&amp; T语法的建议之外,让编译器加载具有最大值的寄存器可能更好。理想的情况是:
/* static __inline__ */ unsigned sadd32 (unsigned a, unsigned b)
{
__asm__ ("addl %k1, %k0\n\t"
"cmovcl %k2, %k0\n\t"
: "+r" (a) : "r" (b), "r" (0xffffffff) : "cc");
return (a);
}
此表单也适用于x86-64,其中第一个和第二个参数分别位于%rdi
(使用%edi
)和%rsi
(使用%esi
) 。使用inline
限定符指定此函数会更好:编译器可能已经加载了'max',或者可能能够安排更好的方法来加载它,等等。它也不需要返回值在%rax
或%eax
。
gcc inline asm的很多教程已经过时了。我找到的最好的是x86 [{64]的Lockless Inc教程。