我正在尝试将x86-64程序集转换为C代码,我仍然不确定条件移动。
这是汇编代码:
public Class Circle{
double radius;
public Circle(){
super();
radius = 1.0;
}
public Circle(double newRadius){
super();
if(newRadius>0)
radius = newRadius;
else
radius = 1.0;
}
public Circle(int newX, int newY, double newRadius){
super(newX,newY);
if(newRadius>0)
radius = newRadius;
else
radius = 1.0;
}
public double getRadius(){
return radius;
}
public void setRadius(double newRadius){
if(newRadius>0)
radius = newRadius;
else
radius = 1.0;
}
}
在C中,它会是:
cmpl %esi, %edi
movl %esi, %eax
cmovge %edi, %eax // This is called a conditional move.
ret
我真的不确定这一切,所以如果有人可以提供帮助,那就太好了。
答案 0 :(得分:2)
条件移动(CMOV)指令到C的最简单转换将是条件运算符。类似的东西:
int a = (b < c) ? b : c;
这基本上允许您将if-else块写为单行。等效的长形if-else块将是:
int a;
if (b < c)
{
a = b;
}
else
{
a = c;
}
在您的情况下,汇编代码使用CMOVGE指令,这意味着“如果将flags设置为指示大于或等于”,则“有条件地将源移动到目标”。 CMP指令用于设置标志。介入的MOV指令只获取为以下CMOV设置的寄存器的内容,而不影响标志。
cmpl %esi, %edi ; compare the value of esi to edi, and set flags
movl %esi, %eax ; move the value of esi into eax
cmovge %edi, %eax ; if flags indicate greater than or equal to (i.e., SF == OF),
; then move the value of edi into eax
因此汇编代码的C转换将是:
eax = (edi >= esi) ? edi : esi;
您可能希望使用描述性变量名,而不是在编写汇编代码时半任意选择的寄存器名称。
至于你要返回的内容,我所知道的所有x86 ABI都会在EAX寄存器中保留函数的返回值。因此,汇编代码返回EAX中剩余的任何值。 (这就是为什么需要介入MOV指令 - 以确保返回值最终在EAX中。)因此,在转换为C时,您可以简单地使用以下单行:
return (edi >= esi) ? edi : esi;
并确保任何编译器都将将转换为等效的汇编代码!
答案 1 :(得分:1)
这实际上取决于您的ABI,但通常eax
是包含返回值的寄存器。
所以它更像是
eax = esi;
if (edi >= esi) eax = edi;
return eax;
相当于
return (edi >= esi ? edi : esi);