您的位置:首页 > 教育 > 培训 > 石家庄网络公司招聘信息_网页升级放问每日正常更新_石家庄百度快照优化排名_搜索引擎优化专员

石家庄网络公司招聘信息_网页升级放问每日正常更新_石家庄百度快照优化排名_搜索引擎优化专员

2025/4/10 21:57:42 来源:https://blog.csdn.net/u011374344/article/details/146914723  浏览:    关键词:石家庄网络公司招聘信息_网页升级放问每日正常更新_石家庄百度快照优化排名_搜索引擎优化专员
石家庄网络公司招聘信息_网页升级放问每日正常更新_石家庄百度快照优化排名_搜索引擎优化专员

JCC(Jump on Condition Code)指的是条件跳转指令,c++中的就是if-else, while, for 等分支循环条件判断的逻辑。它包括很多指令集,各自都不太一样,接下来我尽量将每一个指令的c++ 源码和汇编代码结合起来看,加深学习映像。

学习这章之前还是要了解 EFL 标记寄存器的知识: 汇编学习之《标志寄存器》-CSDN博客

以上标志寄存器部分重点看下  CF,ZF,SF,OF,PF.

理解下面的意思:

cmp x,y 

x -y ==> 影响 CF, ZF 标记位  

情况1  x == y , 计算结果是0, 那么 ZF == 1

情况2  x > y,  计算结果不是0,那么 ZF == 0

情况3 x <  y , 计算结果不是0,但是会发生错位,所以  ZF != 0  and  CF ==  1

JE/JZ (ZF ==1  )

测试:cmp + je  ==> c++ !=  运算

je: jump if equal   

je: jump if zero

判断 ZF ==1 (cmp 计算的结果是0,两个值相等情况)

je 和 jz 在OD上是一样的, 你可以尝试输入jz,但是OD会将其替换成JE

汇编代码

mov DWORD PTR [ebp-0xc], 0x1
mov DWORD PTR [ebp-0x10],0x2
mov eax,DWORD PTR [ebp-0xc]
cmp eax,DWORD PTR [ebp-0x10] 
je 0x401661 <main()+81>   //变量1 == 变量2则跳转走,c++代码就必须是 变量1 != 变量2

我们解释下上面汇编的代码

第一行: 分配了一个变量地址是ebp-0xc,并赋值是1

第二行: 分配了一个变量地址是ebp-0x10,并赋值是2.

第三行: 将第一个地址的值赋值给EAX 累计寄存器

第四行: EAX累计寄存器的值(也就是第一个变量的值)减去第二个变量的值。如果为0,则EFL的ZF标记就会被设置成1,否则为0

第五行: 判断ZF标记是否是1,如果是则调整到main函数的0x401661位置,准备清理资源退出。

c++ 代码

这里可以对照这个c++代码

#include <iostream>

int main() {

    // JE / ZF 比较相等

    int a = 1;  //mov DWORD PTR [ebp-0xc], 0x1

    int b = 2; //mov DWORD PTR [ebp-0x10],0x2

    //mov eax,DWORD PTR [ebp-0xc]
    //cmp eax,DWORD PTR [ebp-0x10]

    //je 0x401661 <main()+81>

    if(a != b) {

        std::cout << "a == b" << std::endl;

    }

    return 0;

}

上面的例子我们先看了汇编语言, 大家应该会发现一个问题, 汇编中跳转的地方指令是je, 也就是比较的两个对象相等(cmp 指令结果是0, zf==1)情况就跳转走了。

JNE/JNZ (ZF == 0  使用c++ ==)

测试:cmp + jne/jnz => c++  ==  运算

jne: jump if not equal

jnz: jump is not zero

就是判断 ZF == 0 

jne/jnz 是满足zf ==0就跳转,也就是cmp运算结果不是0,也就是两个变量是一定不相等(a  != b)就会跳转, c++分支想执行就必须是和a !=0  条件相反, 那么c++ 代码就必须变成 a == 0

修改后c++ 代码

对应的汇编代码:

可以将JE/JZ 例子中的c++代码改成a == b 就可以看到了。

JB/JNAE/JC (CF == 1 )

测试:cmp + JB/JNAE/JC  ==>  c++  >=  运算

jb: jump if below  (无符号比较 低于)

jnae: jump not above or equal 

jc: jump if is carry

判断 CF == 1

同以上汇编反向推导c++代码:

第一步: 定义一个变量,赋值为2, 我们定义变量名称为a

第二步: 定义一个变量, 赋值为1   我们定义变量名称为b

第三步: 比较两个变量

但是怎么写呢? 我先看看 汇编指令是jb ,按照这个跳转指令的的规则,它是判断CF ==1。如果发生了进位或则错位, CF == 1那么就满足条件,就跳转到mian函数401661的地址处。

要满足这个要求,就必须是变量a小于变量b(a < b),这样减法cmp计算才会发生借位。c++代码这里也就是一个判断条件,返回过来它是不希望跳转走,是希望顺序执行的,那么c++代码就必须和刚刚汇编跳转指令相反,也就是a < b相反, 那么就是 a >= b 

以下是c+代码

JNB / JAE / JNC (CF == 0)

测试:cmp + JNB / JAE / JNC == > c++  <  运算

jnb: jump if not below

jae: jump if above or equal

jnc: jump if not carry

判断 CF == 0

这就简单思考下,我c++代码要怎么改,才能验证 JNB/JAE的指令呢?

首先CF == 0,  说明 cmp 指令没有发生借位,也就是 a >= b 这种情况,那么就会跳转执行,我们c++代码要执行分支内的代码,就是不希望跳转走,所以就必须相反, 那么就是和 a >=  b条件相反,也就是a < b, 那么我改动代码验证下,看看c++代码条件比较语句变成a <  b后, 汇编指令是否是  JNB / JAE / JNC.

改动的c++ 代码

汇编代码确认

以上符合预期

JBE / JNA (CF == 1 or ZF == 1 )

测试:cmp + jbe/jna ==> c++ > 运算

jbe: jump if above or equal   <=  

jna: jump if not above   不大于

判断  CF == 1 or ZF == 1

汇编运算

c++ 代码

JA / JNBE (CF == 0 and ZF == 0)

测试:cmp + ja/jnbe ==> c++ <= 运算

ja:  jump if above    >

jnbe: jump if not below or  equal   不小于不等于

判断 CF == 0 and ZF == 0

汇编代码:

c++代码:

JL / JNGE (SF ≠ OF)

jl: jump if less

jnge: jump if not greater or equal

sf: 当前计算语句是负数,sf =1

of: 当前计算语句发生了溢出  of =1

判断 SF ≠ OF  不同情况分析:

情况1 sf == 1 and  of ==0

SF == 1 计算结果为负数, OF == 0 没有发生溢出

a = -5, b = 3

a - 3 = -8  sf =1  of=0, 但是没有发生溢出。

c++ 代码

这里按照上面我们的理解, 汇编要满足小于就跳转走,那c++ 代码要反着写,变成 >=

对应的汇编

情况2: sf == 0  and of == 1

sf == 0 计算结果不是负数, 但是 of ==1 意思是发生了溢出

在看下面代码前,思考下,什么情况下 cmp 减法操作计算结果不是负数,但是发生了溢出?

以32为举例: 32位有符号的整数表示的数据返回是-2147483648--2147483647

a = -2147483648,  b = 1

a - b = 2147483647 //负溢出了 但是计算结果是正数

所以: sf == 0  and of == 1

c++代码:

对应汇编:

JNL / JGE (SF = OF)

jl: jump if not less

jnge: jump if greater and equal

sf: 当前计算语句是负数,sf =1

of: 当前计算语句发生了溢出  of =1

判断  SF = OF

情况1 结果是负数,并且发生溢出

a = 5, b = 6 

cmp a,b  ==> sf =1, of =1 

c++ 代码

汇编代码:

情况2: 计算结果不是负数,且没有发生溢出。

JLE / JNG ( SF ≠ OF   or   ZF == 1)

jle: jump if less or equal

jng: jump if not greater

判断  (SF ≠ OF)    or   ZF == 1

情况1 sf == 1 and  of ==0

SF == 1 计算结果为负数, OF == 0 没有发生溢出

a = -5, b = 3

a - 3 = -8  sf =1  of=0, 但是没有发生溢出。

c++ 代码

汇编

情况2 ZF == 1

c++

汇编:

JG / JNLE ( SF == OF and ZF == 0)

jg: jump if greater

jnle: jump if not less or equal

判断 (SF == OF) and ZF == 0

 计算结果是负数, 并且发生溢出

a = 2147483647   b = -1

cmp a,b

汇编:

JO (OF = =1)

jo: jump if overflow

判断 OF = =1

溢出情况比较好验证,但是反推c++ 代码我还没有实现,后面生深入了后在来补充。

JNO (OF == 0)

jo: jump if not overflow

判断 OF == 0

反推c++ 代码我还没有实现,后面生深入了后在来补充。

JS (SF == 1)

js: jump if sign

判断 SF == 1

反推c++ 代码我还没有实现,后面生深入了后在来补充。

JNS (SF == 0)

jns: jump if not sign

判断 SF == 0

反推c++ 代码我还没有实现,后面生深入了后在来补充。

JP / JPE (PF ==1)

jp: jump if parity (奇偶校验事件)

jpe: jump if parity Event (奇偶校验事件)

判断  PF ==1 表示数据里面的二进制数,1的个数是偶数的情况

JNP / JPO ( PF == 0)

jnp: jump if not parity

jpo: jump if pariry odd (奇数)

判断   PF == 0 表示数据里面的二进制数, 1的个数是奇数

上一篇: 汇编学习之《jmp, nop指令》

下一篇:汇编学习之《call, return指令》

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com