[英]Using AT&T inline assembler for GCC
我正在编写一个简单但有点具体的程序:
目的:根据阶乘计算数字
要求:所有计算都必须在gcc内联asm上完成(at&t语法)
源代码:
#include <iostream>
int main()
{
unsigned n = 0, f = 0;
std::cin >> n;
asm
(
"mov %0, %%eax \n"
"mov %%eax, %%ecx \n"
"mov 1, %%ebx \n"
"mov 1, %%eax \n"
"jmp cycle_start\n"
"cycle:\n"
"inc %%ebx\n"
"mul %%ebx\n"
"cycle_start:\n"
"cmp %%ecx, %%eax\n"
"jnz cycle\n"
"mov %%ebx, %1 \n":
"=r" (n):
"r" (f)
);
std::cout << f;
return 0;
}
此代码导致SIGSEV。
使用intel asm语法的完全相同的程序( http://pastebin.com/2EqJmGAV )可以正常工作。 为什么我的“ AT&T程序”失败了,我该如何解决?
#include <iostream>
int main()
{
unsigned n = 0, f = 0;
std::cin >> n;
__asm
{
mov eax, n
mov ecx, eax
mov eax, 1
mov ebx, 1
jmp cycle_start
cycle:
inc ebx
mul ebx
cycle_start:
cmp eax, ecx
jnz cycle
mov f, ebx
};
std::cout << f;
return 0;
}
UPD:推入堆栈并还原使用过的寄存器将得到相同的结果:SIGSEV
您的输入和输出方式错误。
所以,从改变开始
"=r" (n):
"r" (f)
至:
"=r" (f) :
"r" (n)
然后,我怀疑您将要告诉编译器有关Clobbers(您正在使用的不是输入或输出的寄存器):
因此添加:
: "eax", "ebx", "ecx"
在以上两行之后。
我个人将做出其他一些更改:
1:
和2:
等),这样可以复制代码而无需“重复标签”。 %1
代替%%ebx
这样,您就不会使用额外的寄存器。 %0
直接移动到%%ecx
。 要装载1
到%%eax
两个指令后,所以有它得到了在做什么样的目的%%eax
? [现在,我写的太多了,其他人先回答了...]
编辑:而且,正如安东指出,需要$1
加载常数1, 1
是指从地址1,读不很好地工作,而且最有可能是你的问题的原因
希望没有要求,只使用gcc inline asm来解决它。 您可以使用nasm
转换您的AT&T示例,然后使用objdump
进行反汇编并查看正确的语法。
我似乎还记得,如果您的意思是字面常量而不是内存引用mov 1,%eax
那么mov 1,%eax
应该是mov $1,%eax
。
@MatsPetersson的答案对于内联程序集与编译器(填充/输入/输出寄存器)的交互非常有用。 我一直在关注您得到SIGSEGV
的原因,并且读取地址1
确实可以回答问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.