热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

汇编testq和cmovg指令

如何解决《汇编testq和cmovg指令》经验,为你挑选了1个好方法。

以下是做什么的?

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 = %rdx,a = rax并且c = 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
#include 


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

Matteo Itali.. 5

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

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

是的,这是对的.下面我将尝试展示如何快速"解码"此模式,而不必计算标志寄存器值的所有时间.

注意:英特尔语法提前,因为比较中的操作数顺序更清晰; AT&T很相似,但操作数被颠倒了(更奇怪的角色四处传播).

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

cmp a, b
jCC label

CC这里(条件码)部是指"经营者"(如,>,<,==)你是在之间的比较投入ab; 所以:

jg→" Ĵ如果UMP a reater比b";

jl→" Ĵ如果UMP a比ESS b";

je→" Ĵ如果UMP aË QUAL到b";

jne→" Ĵ如果UMP aÑ OT ë QUAL到b";

ja→" Ĵ UMP如果a一个波夫b";

jb→ " Ĵ如果UMP ab elow b";

......所有的"E"变种(jbe,jae,...)

(在高于/低于耦合来自更大/更小的夫妇的区别在于a/ b是无符号值之间的比较,g/ l为符号值;另外,有很多的同义词,特别je为同义jzAKA"跳如果零",并且jne对于jnzAKA"如果不是零跳";反汇编者可以生产jz或者je,它是相同的)

现在,来看你的情况:

test reg,reg完全等同于cmp reg,0(除了AF的状态,这是无关紧要的); 这很容易理解:

testand在操作数之间执行,并根据结果设置标志; 所以,test reg,reg只需根据reg(and自己的数字是一个nop)设置标志;

cmp b,ab-a根据结果计算和设置标志; 因为b-0 == b,cmp b,0只是设置根据标志b,正是因为test b,b.

cmovgcmovCC指令的一个实例,带有条件代码g,即"如果g reater"则移动.

所以,你的

test rdx,rdx
cmovg rax,rcx

相当于

cmp rdx,0
cmovg rax,rcx

这显然是"将rdx与零进行比较,如果它在rax中更大的移动rcx".



1> Matteo Itali..:

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

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

是的,这是对的.下面我将尝试展示如何快速"解码"此模式,而不必计算标志寄存器值的所有时间.

注意:英特尔语法提前,因为比较中的操作数顺序更清晰; AT&T很相似,但操作数被颠倒了(更奇怪的角色四处传播).

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

cmp a, b
jCC label

CC这里(条件码)部是指"经营者"(如,>,<,==)你是在之间的比较投入ab; 所以:

jg→" Ĵ如果UMP a reater比b";

jl→" Ĵ如果UMP a比ESS b";

je→" Ĵ如果UMP aË QUAL到b";

jne→" Ĵ如果UMP aÑ OT ë QUAL到b";

ja→" Ĵ UMP如果a一个波夫b";

jb→ " Ĵ如果UMP ab elow b";

......所有的"E"变种(jbe,jae,...)

(在高于/低于耦合来自更大/更小的夫妇的区别在于a/ b是无符号值之间的比较,g/ l为符号值;另外,有很多的同义词,特别je为同义jzAKA"跳如果零",并且jne对于jnzAKA"如果不是零跳";反汇编者可以生产jz或者je,它是相同的)

现在,来看你的情况:

test reg,reg完全等同于cmp reg,0(除了AF的状态,这是无关紧要的); 这很容易理解:

testand在操作数之间执行,并根据结果设置标志; 所以,test reg,reg只需根据reg(and自己的数字是一个nop)设置标志;

cmp b,ab-a根据结果计算和设置标志; 因为b-0 == b,cmp b,0只是设置根据标志b,正是因为test b,b.

cmovgcmovCC指令的一个实例,带有条件代码g,即"如果g reater"则移动.

所以,你的

test rdx,rdx
cmovg rax,rcx

相当于

cmp rdx,0
cmovg rax,rcx

这显然是"将rdx与零进行比较,如果它在rax中更大的移动rcx".


推荐阅读
author-avatar
快乐浪迹天涯海绵宝宝_243
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有