将条件移动 (CMOV) 指令从汇编语言翻译成 C

Translating conditional move (CMOV) instructions from assembly into C

我正在尝试将 x86-64 程序集转换为 C 代码,但我仍然不确定条件移动。

这是汇编代码:

cmpl %esi, %edi 
movl %esi, %eax 
cmovge %edi, %eax  // This is called a conditional move.
ret 

在 C 中,会是:

if (edi < esi) { // am I supposed to change edi and esi to local variable names?
   uint32_t variable1; 
   return ___; // what am I supposed to return?
}

我真的不确定这整件事,所以如果有人能提供帮助,那就太好了。

这实际上取决于您的 ABI,但通常,eax 是包含 return 值的寄存器。

所以更像

eax = esi;
if (edi >= esi) eax = edi;
return eax;

相当于

return (edi >= esi ? edi : esi);

条件移动 (CMOV) 指令到 C 的最简单翻译是条件运算符。类似于:

int a = (b < c) ? b : c;

这基本上允许您将 if-else 块写成一行。等效的长格式 if-else 块将是:

int a;
if (b < c)
{
    a = b;
}
else
{
    a = c;
}

在你的例子中,汇编代码使用了 CMOVGE 指令,这意味着 "conditionally move source to destination if flags are set to indicate greater than or equal to"。 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;

您可能希望使用描述性 变量名称,而不是在编写汇编代码时半任意选择的寄存器名称。

至于你会 return,我所知道的所有 x86 ABI 都会在 EAX 寄存器中保留函数的 return 值。因此,汇编代码 returning EAX 中剩余的任何值。 (这就是为什么需要中间的 MOV 指令——以确保 return 值在 EAX 中结束。)因此,在转换为 C 时,您可以简单地使用以下一行代码:

return (edi >= esi) ? edi : esi;

请放心,任何编译器都会将其翻译成等效的汇编代码!