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"