我正在写一个简单但有点特定的程序:
目的:从它的阶乘计算数字
要求:所有计算必须在gcc内联asm上完成(在& 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)的Identic程序运行正常。为什么我的“AT&amp; 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
答案 0 :(得分:4)
你的输入输出错误。
所以,首先要改变
"=r" (n):
"r" (f)
为:
"=r" (f) :
"r" (n)
然后我怀疑你想告诉编译器有关clobbers(你使用的寄存器不是输入或输出):
添加:
: "eax", "ebx", "ecx"
以上两行之后。
我个人会做出一些其他的改变:
1:
和2:
等),这样就可以复制代码而无需“重复标签”。 %1
代替%%ebx
- 这样,您就不会使用额外的注册。 %0
直接移至%%ecx
。您稍后将1
加载到%%eax
两个说明中,那么它在%%eax
中的目的是什么?[现在,我写的太多了,其他人先回答了......]
编辑:而且,正如Anton指出的那样,你需要$1
加载常量1,1
意味着从地址1读取,这不能很好地工作,并且很可能是你的问题
答案 1 :(得分:1)
希望没有任何要求只使用gcc inline asm来解决它。您可以使用nasm
翻译您的AT&amp; T示例,然后使用objdump
反汇编并查看正确的语法。
我似乎记得mov 1,%eax
应该是mov $1,%eax
,如果你的意思是文字常量而不是内存参考。
@MatsPetersson的答案对于内联汇编与编译器(破坏/输入/输出寄存器)的交互非常有用。我专注于您获得SIGSEGV
的原因,并且阅读地址1
确实回答了问题。