C++ 使用AT&;GCC的T内联汇编程序
我正在编写一个简单但有点具体的程序: 目的:根据其阶乘计算数字C++ 使用AT&;GCC的T内联汇编程序,c++,c,assembly,x86,inline-assembly,C++,C,Assembly,X86,Inline Assembly,我正在编写一个简单但有点具体的程序: 目的:根据其阶乘计算数字 要求:所有计算必须在gcc内联asm(at&t语法)上完成 源代码: #include <iostream> int main() { unsigned n = 0, f = 0; std::cin >> n; asm ( "mov %0, %%eax \n" "mov %%e
要求:所有计算必须在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;
}
#包括
int main()
{
无符号n=0,f=0;
标准:cin>>n;
asm
(
mov%0,%%eax\n
“mov%%eax,%%ecx\n”
mov 1,%%ebx\n
mov 1,%%eax\n
“jmp循环\u开始\n”
“循环:\n”
“inc%%ebx\n”
“mul%%ebx\n”
“循环\u开始:\n”
“cmp%%ecx,%%eax\n”
“jnz循环\n”
“mov%%ebx,%1\n”:
“=r”(n):
“r”(f)
);
std::cout>n;
__asm
{
mov-eax,n
mov-ecx,eax
mov-eax,1
mov-ebx,1
jmp循环启动
周期:
ebx公司
多电子束
循环启动:
cmp-eax,ecx
jnz循环
mov f,ebx
};
std::cout希望除了gcc内联asm之外,不需要其他任何东西。您可以使用nasm
翻译您的AT&T示例,然后使用objdump
反汇编,并查看正确的语法
我似乎记得mov1,%eax
应该是mov$1,%eax
,如果你指的是文字常量而不是内存引用的话
@matstpeterson的回答对于内联程序集与编译器的交互(clobbered/input/output registers)非常有用。我重点讨论了您获得SIGSEGV
的原因,阅读地址1
确实回答了这个问题。您的输入和输出方式是错误的
所以,从改变开始
"=r" (n):
"r" (f)
致:
然后,我怀疑您会想告诉编译器关于clobber(您正在使用的不是输入或输出的寄存器):
因此,请加上:
: "eax", "ebx", "ecx"
在上面的两行之后
我个人会做一些其他的改变:
使用本地标签(1:
和2:
等),这样可以在不使用“重复标签”的情况下复制代码
使用%1
而不是%%ebx
——这样,您就不会使用额外的寄存器
将%0
直接移动到%%ecx
。您稍后将1
加载到%%eax
两条指令中,那么它在%%eax
中有什么用途呢
[现在,我写的太多了,其他人先回答了…]
编辑:正如安东指出的,你需要$1
来加载常量1,1
意味着从地址1读取,这不太好,很可能是你的问题的原因我不是内联汇编专家,但是你不需要告诉编译器你正在使用哪个寄存器,这样它就可以保护它们了吗?在MSVC中,我明确地说不是。我试图保存使用过的寄存器以进行堆栈和还原。结果是一样的-SIGSEV。不要告诉我我不能使用stack=)@quizzer:GCC在内联汇编块中保留寄存器(或通知编译器哪些寄存器不保留)方面与MSVC有不同的要求。除了在其他版本的代码中也不需要它,是吗?
"=r" (f) :
"r" (n)
: "eax", "ebx", "ecx"