c - 汇编testq和cmovg指令

标签 c assembly x86 x86-64 intel

以下是做什么的?

testq   %rdx, %rdx
cmovg   %rcx, %rax

我知道 testq 是按位和两个寄存器之间的,但它如何与标志一起使用? 这将在 c 中转化为什么? 例如如果 %rdx 将保存值 0x01,那么我们将有 0x01 & 0x01 = 0x01,这将设置

ZF = 0, SF = 0, OF = 0.

对于我能找到的 cmovg 执行如果

˜(SF ˆ OF) & ˜ZF

这将解析为

˜(0 ˆ 0) & ˜0 = ˜(0) & ˜0 = 1 & 1 = 1.

这是否意味着将执行 cmovg 并且相应的 c 代码将针对 d = %rdxa = raxc = rcx:

 if(d > 0){
   a = c;
 }

或者有人可以换句话解释一下吗?

此外,我一直在尝试将此程序集转换为相应的 C 代码。目前我得到的结果就像 testq %rdx, %rdx with jne .L4 上的无限 while 循环。附上上述内容。任何人都知道正确的解决方案是什么?我目前的解决方案是这样的:

p:
        movq    (%rdi), %rdx
        testq   %rdx, %rdx
        je      .L5
        movl    $0, %eax
.L4:
        leaq    (%rax,%rdx), %rcx
        testq   %rdx, %rdx
        cmovg   %rcx, %rax
        addq    $8, %rdi
        movq    (%rdi), %rdx
        testq   %rdx, %rdx
        jne     .L4
        ret
.L5:
        movl    $0, %eax
        ret

解决方案(错误):

#include<stdlib.h>
#include <stdio.h>


int func(int *rdi){
  int rdx = *rdi;
  if(rdx == 0){
    int rax = 0;
    return rax;
  }
  int rax = 0;
    do {
    int rcx = rax + rdx;
    if(rdx > 0){
      rax = rcx;
    }
    rdi += 8;
    rdx = *rdi;
  } while(rdx != 0);

  return rax;

}

  int main(int argc, char const *argv[]) {
    int var = 20;
    int *ip;
    ip = &var;
    func(ip);
  }

最佳答案

(转自评论,回复原问题)

if(d > 0){
    a = c;
}

是的,这是正确的。下面我将尝试展示如何快速“解码”这个模式,而不必一直计算标志寄存器值。

Notice: Intel syntax ahead, as it's way clearer for the operands order in comparisons; AT&T is similar but with the operands reversed (and more strange characters spread around).

“数字比较”条件代码最好在“经典”序列的上下文中理解

cmp a, b
jCC label

CC (条件代码)此处的部分指的是您在 > 之间进行比较的“运算符”(如 <==a)和 b ;所以:

  • jg → "j如果a g大于b 则跳转";
  • jl → "j如果 a 小于 b l ";
  • je → "j如果a e等于b ";
  • jne → "j如果a ne等于b ";
  • ja → "j如果 above b ";
  • jb → "j如果ab低于b 则跳转";
  • ...所有“e”变体(jbejae、...)

(上/下对与大/小对的不同之处在于a/b 用于无符号值之间的比较,g/l 用于有符号值;此外,还有a lot of synonyms ,特别是 jejz AKA“如果为零则跳转”的同义词,jne 对于 jnz 又称为“如果不为零则跳转”;反汇编程序可能会产生 jzje,它们是一样的)

现在,进入你的案例:

  • test reg,reg完全等同于 cmp reg,0 ( apart from the status of AF ,这是无关紧要的);这很容易理解:
    • test执行 and在操作数之间并根据结果设置标志;所以,test reg,reg只需根据 reg 设置标志(and 对一个数字本身进行 nop);
    • cmp b,a计算 b-a并根据结果设置标志;鉴于b-0 == b , cmp b,0只需根据 b 设置标志, 与 test b,b 完全一样.
  • cmovgcmovCC 的一个实例指令,条件代码 g ,即“如果 greater 则移动”。

那么,你的

test rdx,rdx
cmovg rax,rcx

相当于

cmp rdx,0
cmovg rax,rcx

它清楚地读作“将 rdx 与零进行比较,如果它更大,则在 rax 中移动 rcx”。

关于c - 汇编testq和cmovg指令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46570431/

相关文章:

ios - 我如何在 Rubymotion 中编写此 C 代码?

c - 字符串 "abc 123 456"的 sscanf 格式是什么

assembly - x86-64 和远程调用/跳转

c++ - x64 性能与 x86 相比

c++ - 我的 x86 目标文件中这些看似无用的 callq 指令有什么用?

c - C 中的星号空格 - 额外的空格是什么意思?

C 函数的复杂性

c# - 我如何在字符串变量中运行 ASM 操作码或将其转换为字节?

c - 无法识别的选项“-tree-vectorize”

ios - 在 ARM 组件中使用堆栈指针(sp)