GCC内联汇编程序输出问题
我试图通过移位和加法在汇编程序中进行乘法运算,从下面的代码中得到最奇怪的输出。如果int main中的最后两个函数调用被注释掉,我会得到一个正常的结果,但如果不是,我会得到第一个调用的正常结果,以及第二个和第三个调用的两个垃圾结果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
#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正如上面的注释所说,您应该让编译器选择寄存器。