GCC内联汇编程序输出问题

GCC内联汇编程序输出问题,gcc,assembly,Gcc,Assembly,我试图通过移位和加法在汇编程序中进行乘法运算,从下面的代码中得到最奇怪的输出。如果int main中的最后两个函数调用被注释掉,我会得到一个正常的结果,但如果不是,我会得到第一个调用的正常结果,以及第二个和第三个调用的两个垃圾结果 #include <iostream> using namespace std; int times_ten(int multiply_by_ten) { int multiplied_by_ten = 0; //this multip

我试图通过移位和加法在汇编程序中进行乘法运算,从下面的代码中得到最奇怪的输出。如果int main中的最后两个函数调用被注释掉,我会得到一个正常的结果,但如果不是,我会得到第一个调用的正常结果,以及第二个和第三个调用的两个垃圾结果

#include <iostream>

using namespace std;

int times_ten(int multiply_by_ten)
{
    int multiplied_by_ten = 0;
    //this multiplies by 10
    __asm__("shld   %%eax,%1;"
                  "movl %%eax,%%ebx;"
                  "shld  %%eax,%1;"
                  "shld  %%eax,%1;"
                  "addl  %%ebx,%%eax;"
                  : "=r" (multiplied_by_ten)
                  : "a" (multiply_by_ten)
    );

    return multiplied_by_ten;
}
int times_hundred(int multiply_by_hundred)
{
    int multiplied_by_hundred = 0;
    //this multiplies by 100
    __asm__("shld   %%eax,%1;"
                  "shld   %%eax,%1;"
                  "movl %%eax,%%ebx;"
                  "shld  %%eax,%1;"
                  "shld  %%eax,%1;"
                  "shld  %%eax,%1;"
                  "movl %%eax,%%edx;"
                  "shld  %%eax,%1;"
                  "addl  %%ebx,%%eax;"
                  "addl  %%edx,%%eax;"
                  : "=r" (multiplied_by_hundred)
                  : "a" (multiply_by_hundred)

    );

    return multiplied_by_hundred;
}
int main()
{
    cout<<times_hundred(1)<<endl;
    cout<<times_ten(1)<<endl;
    cout<<times_hundred(1)<<endl;

    return 0;
}

修复%%clobber问题后,更改输出寄存器:

...
"addl  %%edx,%%eax;"
              : "=a" (multiplied_by_hundred)
              : "a" (multiply_by_hundred)
              : "%eax", "%ebx", "%edx"
从“=r”到“=a”。 编辑:
这适用于clang,但不适用于gcc。抱歉。

解决%%clobber问题后,请更改输出寄存器:

...
"addl  %%edx,%%eax;"
              : "=a" (multiplied_by_hundred)
              : "a" (multiply_by_hundred)
              : "%eax", "%ebx", "%edx"
从“=r”到“=a”。 编辑: 这适用于clang,但不适用于gcc。抱歉。

此代码现在可以使用了

#include <iostream> 

using namespace std; 

int times_ten(int multiply_by_ten) 
{ 
         int multiplied_by_ten = 0; 
         //this multiplies by 10 
         __asm__("shl   $1, %%eax;" 
                                   "movl %%eax,%%ebx;" 
                                   "shl  $2, %%eax;" 
                                   "addl  %%ebx,%%eax;" 
                                   : "=a" (multiplied_by_ten) 
                                   : "0" (multiply_by_ten) : "%ebx" 
         ); 

         return multiplied_by_ten; 
} 
int times_hundred(int multiply_by_hundred) 
{ 
         int multiplied_by_hundred = 0; 
         //this multiplies by 100 
         __asm__("shl   $2, %%eax;" 
                                   "movl %%eax,%%ebx;" 
                                   "shl  $3, %%eax;" 
                                   "movl %%eax,%%edx;" 
                                   "shl  $1, %%eax;" 
                                   "addl  %%ebx,%%eax;" 
                                   "addl  %%edx,%%eax;" 
                                   : "=a" (multiplied_by_hundred) 
                                   : "0" (multiply_by_hundred) : "%ebx","%edx" 

         ); 

         return multiplied_by_hundred; 
} 
int main() 
{ 
         cout<<times_hundred(1)<<endl; 
         cout<<times_ten(1)<<endl; 
         cout<<times_hundred(1)<<endl; 

     return 0; 
} 
#包括
使用名称空间std;
整数乘以十(整数乘以十)
{ 
整数乘以十等于0;
//这乘以10
__asm_uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
movl%%eax,%%ebx
shl$2,%%eax
添加%%ebx,%%eax
:“=a”(乘以十)
:“0”(乘以十):%ebx”
); 
返回值乘以十;
} 
整数乘以一百(整数乘以一百)
{ 
int乘以_乘以_百=0;
//这乘以100
__asm_uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
movl%%eax,%%ebx
shl$3,%%eax
movl%%eax,%%edx
shl$1,%%eax
添加%%ebx,%%eax
添加%%edx,%%eax
:“=a”(乘以一百)
:“0”(乘以100):%ebx”,“%edx”
); 
返回值乘以一百;
} 
int main()
{ 
cout这个代码现在可以工作了

#include <iostream> 

using namespace std; 

int times_ten(int multiply_by_ten) 
{ 
         int multiplied_by_ten = 0; 
         //this multiplies by 10 
         __asm__("shl   $1, %%eax;" 
                                   "movl %%eax,%%ebx;" 
                                   "shl  $2, %%eax;" 
                                   "addl  %%ebx,%%eax;" 
                                   : "=a" (multiplied_by_ten) 
                                   : "0" (multiply_by_ten) : "%ebx" 
         ); 

         return multiplied_by_ten; 
} 
int times_hundred(int multiply_by_hundred) 
{ 
         int multiplied_by_hundred = 0; 
         //this multiplies by 100 
         __asm__("shl   $2, %%eax;" 
                                   "movl %%eax,%%ebx;" 
                                   "shl  $3, %%eax;" 
                                   "movl %%eax,%%edx;" 
                                   "shl  $1, %%eax;" 
                                   "addl  %%ebx,%%eax;" 
                                   "addl  %%edx,%%eax;" 
                                   : "=a" (multiplied_by_hundred) 
                                   : "0" (multiply_by_hundred) : "%ebx","%edx" 

         ); 

         return multiplied_by_hundred; 
} 
int main() 
{ 
         cout<<times_hundred(1)<<endl; 
         cout<<times_ten(1)<<endl; 
         cout<<times_hundred(1)<<endl; 

     return 0; 
} 
#包括
使用名称空间std;
整数乘以十(整数乘以十)
{ 
整数乘以十等于0;
//这乘以10
__asm_uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
movl%%eax,%%ebx
shl$2,%%eax
添加%%ebx,%%eax
:“=a”(乘以十)
:“0”(乘以十):%ebx”
); 
返回值乘以十;
} 
整数乘以一百(整数乘以一百)
{ 
int乘以_乘以_百=0;
//这乘以100
__asm_uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
movl%%eax,%%ebx
shl$3,%%eax
movl%%eax,%%edx
shl$1,%%eax
添加%%ebx,%%eax
添加%%edx,%%eax
:“=a”(乘以一百)
:“0”(乘以100):%ebx”,“%edx”
); 
返回值乘以一百;
} 
int main()
{ 

你可能需要eax,abx,edx在你的clobber列表中。我试过了,但它不会编译。你说“不会编译”是什么意思?发布实际的代码和实际的错误消息。你知道gcc非常擅长做这种优化(包括倒数乘法除法)使用普通的C运算符和
-O2
,对吗?这不需要绑定到特定的寄存器。因此,您编写此汇编程序例程的原因可能是出于教育目的?在任何情况下,您都希望摆脱像
%%eax
这样的东西,转而使用
r()
constraint,如果性能非常重要。否则,您将不必要地妨碍编译器的寄存器分配。%%eax正在对特定寄存器进行硬编码。您可以像以前那样将某些变量绑定到=r(),但也可以将输入绑定到r()并以这种方式分配所需的任何局部变量。您可以引用寄存器,例如使用%0、%1等(或通过绑定名称),它使用编译器认为在其分配策略中最好的寄存器,而不是强制执行特定的寄存器,这很可能会迫使编译器生成额外的移动。您可能需要在clobber列表中使用eax、abx、edx。我尝试过,但它不会编译。您所说的“不会编译”是什么意思?发布实际代码和实际错误消息。您知道gcc非常擅长进行此类优化(包括倒数乘法除法)使用普通的C运算符和
-O2
,对吗?这不需要绑定到特定的寄存器。因此,您编写此汇编程序例程的原因可能是出于教育目的?在任何情况下,您都希望摆脱像
%%eax
这样的东西,转而使用
r()
constraint,如果性能非常重要。否则,您将不必要地妨碍编译器的寄存器分配。%%eax正在对特定寄存器进行硬编码。您可以像以前那样将某些变量绑定到=r(),但也可以将输入绑定到r()并以这种方式分配所需的任何局部变量。您可以引用寄存器,例如使用%0、%1等(或通过绑定名称),它使用编译器认为在其分配策略中最好的寄存器,而不是强制执行特定的寄存器,这很可能会迫使编译器生成额外的移动。这两个字母是什么意思…r和a?这两个字母是什么意思…r和a?正如上面的注释所说,您应该让编译器选择regis正如上面的注释所说,您应该让编译器选择寄存器。