条件码
CPU维护一组单个位的条件码寄存器
- CF:进位标志。最近的操作使最高位产生了进位。可用来检查无符号操作的溢出。
- ZF:零标志。最近的操作得出得结果为0。
- SF:符号标志。最仅的操作得到的结果为负数。
- OF:溢出标志。最近的操作导致一补码溢出——正溢出或负溢出。
leaq指令是用来进行地址计算的,不改变任何条件码。
| 指令 | 基于 | 描述 |
|---|---|---|
| CMP S1, S2 | S2 - S1 | 比较 |
| cmpb | 比较字节 | |
| cmpw | 比较字 | |
| cmpl | 比较双字 | |
| cmpq | 比较四字 | |
| TEST S1, S2 | S1 & S2 | 测试 |
| testb | 测试字节 | |
| testw | 测试字 | |
| testl | 测试双字 | |
| testq | 测试四节 |
比较和测试指令。这些指令不修改任何寄存器的值,只设置条件码
访问条件码
| 指令 | 同义名 | 效果 | 设置条件 |
|---|---|---|---|
| sete D | setz | D<—ZF | 相等/零 |
| setne D | setnz | D<—~ZF | 不等/非零 |
| sets D | D<—SF | 负数 | |
| setns D | D<—~SF | 非负数 | |
| setg D | setnle | D<— ~(SF^OF)&~ZF | 大于(有符号>) |
| setge D | setnl | D<— ~(SF^OF) | 大于等于(有符号>=) |
| setl D | setnge | D<— SF^OF | 小于(有符号<) |
| setle D | setng | D<— (SF^OF) | ZF |
| seta D | setnbe | D<—~CF&~ZF | 超过(无符号>) |
| setae D | setnb | D<—~CF | 超过或相等(无符号>=) |
| setb D | setnae | D<—CF | 低于(无符号<) |
| setbe D | setna | D<—CF|ZF | 低于或相等(无符号<=) |
SET指令。每条指令根据条件码的某种组合,将一个字节设置为0或者1。有些指令有” 同义名” ,也就是同一条机器指令有别的名字。
跳转指令
| 指令 | 同义名 | 跳转条件 | 描述 |
|---|---|---|---|
| jmp Label | 1 | 直接跳转 | |
| jmp *Operand | 1 | 间接跳转 | |
| je Label | jz | ZF | 相等/零 |
| jne Label | jnz | ~ZF | 不相等/非零 |
| js Label | SF | 负数 | |
| jns Label | ~SF | 非负数 | |
| jg Label | jnle | ~(SF^OF)&~ZF | 大于(有符号>) |
| jge Label | jnl | ~(SF^OF) | 大于或等于(有符号>=) |
| jl Label | jnge | SF^OF | 小于(有符号<) |
| jle Label | jng | (SF^OF)|ZF | 小于或等于(有符号<=) |
| ja Label | jnbe | ~CF&~ZF | 超过(无符号>) |
| jae Label | jnb | ~CF | 超过或相等(无符号>=) |
| jb Label | jnae | CF | 低于(无符号<) |
| jbe Label | jna | CF | ZF |
jump指令。当跳转条件满足时,这些指令会跳转到一条带标号的目的地。有些指令有” 同义名 “,也就是同一条机器指令的别名
跳转目的地通常用一个标号(Label)指明,类似 “.L1” 。跳转有直接跳转”jmp .L1”或者间接跳转”jmp *%rax”用寄存器和内存中的值作为跳转目标。
跳转指令的编码可以用绝对地址或相对地址,相对地址利用jmp指令后面对应的值+下一条指令的起始地址=跳转目的地,这也方便程序在内存中的移动,最为常用。使用如下例:
movq %rdi, %rax jmp .L2 .L3: sarq %rax .L2: testq %rax, %rax jg .L3 rep; ret
讯享网
汇编器产生的 ” .o ” 格式的反汇编版本如下:
讯享网0:48 89 f8 mov %rdi, %rax 3:eb 03 jmp 8 <loop+0x8> 5:48 d1 f8 sar %rax 8:48 85 c0 test %rax, %rax b:7f f8 jg 5 <loop+0x5> d:f3 c3 repz retq
- 对于jmp 8; 用 0x03(二进制补码)+5 = 0x8 即可得到跳转到8
- 对于jg 5; 用 0xf8(二进制补码)+0xd = 0x5 即可得到跳转到5
现代使用条件传送来实现条件分支
long absdiff(long x, long y) { long result; if(x < y) result = y-x; else result = x-y; return result; }
优化的汇编
讯享网long absdiff(long x, long y) x in %rdi, y in %rsi absdiff: movq %rsi, %rdx subq %rdi, %rdx rval = y-x movq %rdi, %rax subq %rsi, %rax eval = x-y cmpq %rsi, %rdi compare x:y cmovl %rdx, %rax if x<y, eval = rval ret return eval
以上汇编的实现原理可以使用如下的C语言来解释
long cmovdiff(long x, long y) { long rval = y-x; long eval = x-y; long ntest = x >= y; /* Line below requires * single instruction: */ if(ntest) rval = eval; return rval; }
条件传送指令
| 指令 | 同义名 | 传送条件 | 描述 |
|---|---|---|---|
| cmove S, R | cmovz | ZF | 相等/零 |
| cmovne S, R | cmovnz | ~ZF | 不相等/非零 |
| cmovs S, R | SF | 负数 | |
| cmovns S, R | ~SF | 非负数 | |
| cmovg S, R | cmovnle | ~(SF^OF)&~ZF | 大于(有符号>) |
| cmovge S, R | cmovnl | ~(SF^OF) | 大于或等于(有符号>=) |
| cmovl S, R | cmovnge | SF^OF | 小于(有符号<) |
| cmovle S, R | cmovng | (SF^OF)|ZF | 小于或等于(有符号<=) |
| cmova S, R | cmovnbe | ~CF&~ZF | 超过(无符号>) |
| cmovae S, R | cmovnb | ~CF | 超过或相等(无符号>=) |
| cmovb S, R | cmovnae | CF | 低于(无符号<) |
| cmovbe S, R | cmovna | CF|ZF | 低于或相等(无符号<=) |
条件传送指令。当传送条件满足时,指令把源值S复制到目的R。有些指令是” 同义名” ,即同一条机器指令的不同名字

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/19096.html