美文网首页
程序的机器级表示-跳转

程序的机器级表示-跳转

作者: Teech | 来源:发表于2019-04-28 23:26 被阅读0次

条件码

除了整数寄存器,cpu还维护着一组单个条件码的寄存器,他们用来描述最近算术和逻辑操作的属性。可以检测这些寄存器来执行分支指令。常见的条件码有:
CF:进位标志。最近的操作产生了最高位产生了进位,可以检查无符号数操作的溢出。
ZF:0标志,最近操作结果为0.
SF:符号标志。最近的操作结果得到了负数。
OF:最近的操作产生了补码溢出(正溢出或者负溢出)
可以举例子说明比如一条ADD指令 t = a + b。
(unsigned)t < (unsigned)a 得出 无符号整数加法溢出了 CF设置了
t = 0 得出 ZF标志设置 产生0了
t < 0 得出 SF标志设置 操作结果得到负数
(a < 0 == b<0) AND (t < 0 != a<0) 可以得出产生了溢出 设置OF。
证明下这个表达式 当产生溢出的时候肯定都是a,b同符号。分两种情况。

  1. 当a > 0,b>0 如果产生溢出,那么 t <= 0
    2.当a< 0,b<0 如果负溢出,那么 t >=0
    表达式拆分后刚好是这两种情况。
    leaq指令不改变条件码,因为是进行地址计算的(这里只能记住就这样了)。 其他指令会修改条件码。
    xor指令,CF标志和OF标志都会被设置,移位操作,进位标志被设置成最后一个被移出的位,溢出操作被设置成0。INC和DEC指令会设置OF标志和ZF标志不会改变CF标志。
    除了上述这些指令还有两类指令CMP和TEST指令只改变条件不改变其他寄存器。
  • CMP S_1,S_2 基于S_2 - S_1 比较
  • TEST S_1,S_2 基于S_1 & S_2 测试
    CMP指令和SUB行为一样的,如果两个数相等ZF会设置成1,其他标志可以确定两个操作数之间的大小关系。
    TEST指的行为和AND指令一样。常用的用法是 testq %rax,%rax来检查%rax是否是负数,零还是正数。或者一个操作码位掩码来指示那些位需要被测试。

访问条件码

条件码一般不会直接被读取,具体应用的形式

  • 根据条件码的某种组合,把一个字节设置成0或者1。比如SET指令的应用。
   int c = a > b;
   反汇编后的结果: 
   cmp    -0x8(%rbp),%eax #比较 a > b
   setg   %al                        #如果大于的话 设置%al为1 否则设置0
   movzbl %al,%eax           #拓展字节到双字

setl 表示< \Leftrightarrow 无溢出负数SF&~OF 或者负溢出结果为正数~SF&OF。合并两个表达式SF^OF.
setle 表示\leq \Leftrightarrow (SF^OF) | ZF
setg以及setge分别对上面的表达式取反即可。

跳转指令编码

跳转指令一般都是相对pc指针的编码的。

if(a > 0)
  a= a +1;
反汇编结果如下:
83 7d fc 00             cmpl   $0x0,-0x4(%rbp)
7e 04                   jle    e <main+0xe>
83 45 fc 01             addl   $0x1,-0x4(%rbp)
第二行的7e 04 7e表示jle指令,04表示pc指针+4,不难看出第三行指令占用了4个字节,所以刚好跳转到下一条指令。这段目标代码可以不做改变就可以移动到内存的任意位置。

用条件控制来实现分支

将c语言的表达式翻译成汇编,最常见的方式是结合有条件和无条件跳转。

c语言中 if-else 通用模板为
if (test-exp)
  then-statement
else
  else-statement
对于这种形式,汇编实现往往会用这种形式
  t = test-exp
  if (!t)
    goto false;
  then-statement
  goto done;
false:
  else-statement
done:  

用条件传送实现条件分支

实现条件操作的传统方法是使用控制的条件转移,当条件满足时沿一条执行路径走,不满足时沿另一条路径走。这种方式很低效。一种替代策略是使用“数据的条件转移”,这种方法计算条件操作的两个结果,在 根据条件选择其中一个。

long absdiff(long x,long y){ 
    long result;
    if(x<y)
        result = y-x;
    else
        result = x-y;
    return result;
}
选择O0去编译得到结果
48 89 7d e8             mov    %rdi,-0x18(%rbp)
48 89 75 e0             mov    %rsi,-0x20(%rbp)
48 8b 45 e8             mov    -0x18(%rbp),%rax
48 3b 45 e0             cmp    -0x20(%rbp),%rax
7d 0e                   jge    24 <absdiff+0x24>
48 8b 45 e0             mov    -0x20(%rbp),%rax
48 2b 45 e8             sub    -0x18(%rbp),%rax
48 89 45 f8             mov    %rax,-0x8(%rbp)
eb 0c                   jmp    30 <absdiff+0x30>
48 8b 45 e8             mov    -0x18(%rbp),%rax
48 2b 45 e0             sub    -0x20(%rbp),%rax
48 89 45 f8             mov    %rax,-0x8(%rbp)

选择O1去编译得到的结果
48 89 f2                mov    %rsi,%rdx
48 29 fa                sub    %rdi,%rdx
48 89 f8                mov    %rdi,%rax
48 29 f0                sub    %rsi,%rax
48 39 f7                cmp    %rsi,%rdi
48 0f 4c c2             cmovl  %rdx,%rax

可以观察到O0没有优化,是根据条件转移来控制分支的,O1下优化后,通过条件传送来实现分支的。
这么优化可以带来性能的提成,除了上述指令条数减少外。其实在cpu内部指令并不是串行的,而是每个阶段执行所需操作的一部分,这种重叠指令的方式来获取性能的提升。比如取一条指令的同时计算前面一条指令的算术运算。所以需要流水线里充满待执行的指令序列。当遇到条件跳转时,需要先获取值然后在能决定往哪里跳转。处理器会猜测一个方向,只要猜测可靠,那么流水线里就会充满指令。错误的预测会丢掉之前的工作,然后重新从开始正确的位置开始填充流水线,一个错误预测会有15到30个的时钟周期惩罚。
使用条件传送,可以保证流水线里充满着指令
用条件传送法编译出来的抽象代码描述
v = then-state
ve = else-state
t = test-exp
if(!t)
  v = ve

相关文章

  • 程序的机器级表示-跳转

    条件码 除了整数寄存器,cpu还维护着一组单个条件码的寄存器,他们用来描述最近算术和逻辑操作的属性。可以检测这些寄...

  • 程序的机器级表示

    在计算机系统中,程序的运行离不开CPU、内存等之间的协作。而在CPU中, 其内部的寄存器起到了十分重要的作用,有...

  • 程序的机器级表示

    计算机系统使用了多种不同的抽象,利用简单的抽象模型来隐藏实现的细节。对于机器级编程来说,其中两种抽象尤为重要。第一...

  • 程序的机器级表示

    本文是对《深入理解计算机系统》第3章的一些总结。 什么是机器级程序机器级程序只是一系列的字节序列,由多条指令组成,...

  • 程序的机器级表示

    计算机执行机器代码,用字节序列编码低级的操作,包括处理数据、管理存储器、读写存储设备上的数据,以及利用网络通信。编...

  • 第三章:程序的机器级表示

    程序的机器级表示 程序编码 机器级代码 数据格式 字word表示16位数据类型,32位数为双字double wor...

  • 2,程序的机器级表示

    一, 编译使用命令 1, 汇编命令 2, intel 汇编指令 3, 反编译 命令 二, 汇编指令 1, mov...

  • Charpter Three 程序的机器级表示

    3.2 程序编码3.2.1 机器级表示抽象计算机系统使用了多种不同形式的抽象, 利用更简单的抽象模型来隐藏实现的细...

  • 程序的机器级表示-基本操作

    程序编码 机器级代码 理解机器级代码有2种抽象需要理解。 指令集架构:来定义机器级程序的格式以及行为。定义了处理器...

  • 程序的机器级表示 -- 控制(一)

    《深入理解计算机系统(第三版)》阅读随笔 在 C 语言中,可以使用条件语句、循环语句和分支语句来控制程序的执行流程...

网友评论

      本文标题:程序的机器级表示-跳转

      本文链接:https://www.haomeiwen.com/subject/knxagqtx.html