汇编testq和cmovg指令

时间:2017-10-04 17:06:10

标签: 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上的无限while循环,%rdx与jne .L4。随着上面的内容被封闭。谁知道正确的解决方案是什么?我目前的解决方案是:

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);
  }

1 个答案:

答案 0 :(得分:5)

(从评论中移出,回复原始问题)

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

是的,这是对的。下面我将尝试展示如何解码&#34;这种模式很快,无需计算标志寄存器值的所有时间。

  

注意:英特尔语法提前,因为它在比较中的操作数顺序更清晰; AT&amp; T类似但与操作数相反(并且更多奇怪的字符在周围传播)。

&#34;数字比较&#34;条件代码最好在&#34; classic&#34;的背景​​下理解。序列

cmp a, b
jCC label

这里的CC(条件代码)部分是指&#34;运算符&#34; (例如,><==)您在ab之间进行比较;这样:

  • jg→&#34; j ump如果a g b&#34;; < / LI>
  • jl→&#34; j ump如果a l ess比b&#34 ;; < / LI>
  • je→&#34; j ump,如果a e 符合b&#34 ;; < / LI>
  • jne→&#34; j 如果a n e 符合{{{ 1}}&#34 ;;
  • b→&#34; j 如果ja a bove a&#34 ;;
  • b→&#34; j ump如果jb b elow a&#34 ;;
  • ...所有&#34; e&#34;变体(bjbe,...)

(上面/下面的情侣不同于较大/较少情侣jae / a用于比较无符号值,b / g表示有符号值另外,还有a lot of synonyms,特别是lje AKA的同义词&#34;如果为零则跳转为#34;以及jzjne } AKA&#34;跳跃,如果不是零&#34 ;;反汇编者可以产生jnzjz,它是相同的)

现在,来看你的情况:

  • je完全等同于test reg,regapart from the status of AF,这是无关紧要的);这很容易理解:
    • cmp reg,0在操作数之间执行test并根据结果设置标志;所以,and只根据test reg,reg设置标记(reg一个数字本身就是一个nop);
    • and计算cmp b,a并根据结果设置标志;鉴于b-ab-0 == b只根据cmp b,0设置标记,与b完全相同。
  • test b,bcmovg指令的一个实例,条件代码为cmovCC,即&#34;如果 g reater&#34;则移动。

所以,你的

g

相当于

test rdx,rdx
cmovg rax,rcx

明确地将其读作&#34;将rdx与零进行比较,如果它在rax&#34;中移动rcx更大。