吾爱汇编

 找回密码
 立即注册

QQ登录

绑定QQ避免忘记帐号

查看: 2694|回复: 9

[转载技术] 第六章-比较和条件跳转指令

[复制链接]
Shark恒 发表于 2015-1-20 15:42 | 显示全部楼层 |阅读模式

                                           第六章-比较和条件跳转
通常情况下,比较指令有两个操作数,并根据比较的结果来决定程序是否跳转到后面的分支中。
我们知道,当注册程序要求我们输入序列号的时候,这个时候,程序会执行一条或者多条比较指令,根据比较的结果来判断你输入的序列号是否正确。
接下来,我们将详细介绍比较和跳转指令。
我们知道,某些指令的指令会影响到标志位,最常见的就是零标志位Z。
CMP
该指令是比较两个操作数,实际上,它相当于SUB指令,但是相减的结构并不保存到第一个操作数中。只是根据相减的结果来改变零标志位的,当两个操作数相等的时候,零标志位置1。
看看下面的例子:
CMP EAX, ECX
EAX与ECX相减,它们本身的值并不改变,只是根据它们相减的结果来决定零标志位Z是否置1。在OD中来看一个例子。
image002.jpg
写入CMP EAX,ECX指令并修改EAX和ECX的值,让它们相等。
image004.jpg
按下F7键,可以看到EAX和ECX的值并没有改变,但是相减的结果是零标志位Z被置为了1,我们在OD来看一个例子。
image006.jpg
实际上,我们并不关心相减的确切结果,我们只关心EAX和ECX是否相等。
虽然我们还没有介绍条件跳转,这里简单提一下,有两种可能性:根据标志的值来决定跳转还是不跳转。最简单的例子就是配合JZ指令,如果Z标志被置为1,就跳转,否则,就不跳转。

如果有两个序列号做比较,例如EAX存放的是你输入的序列号,ECX存放的是正确的序列号,该程序使用CMP指令来比较,如果它们两个是相等的,那么零标志位Z就置为1,后面JZ指令就会跳转到注册成功的部分。如果EAX不等于ECX的话,那么零标志位就会置0,那么就不会跳转到注册成功的部分。
让我们来看看有关条件跳转的一个更具体的例子。
符号标志位S是比较第一个操作数是否大于第二个操作数。
让我们来看下面的例子:
重新写入CMPEAX,ECX指令,但是现在要求是EAX的值要大于ECX的值。
image008.jpg
按下F7键:
image010.jpg
可以看到,零标志位Z是0,所以我们知道,这两个值并不相等,并且符号标志位S也等于0,我们就可以得知EAX-ECX结果是正的。也就说明EAX大于ECX。
依然是CMP EAX,ECX指令,但这次是EAX小于ECX。
image012.jpg
然后按下F7键:
image014.jpg
这里我们可以看到,EAX减去ECX的结果是负的,也就是说ECX大于EAX。所以符号标志位S被置为了1。
根据比较的不同结果来设置相应的标志位,来决定程序应该走哪个分支。此外,CMP指令还允许寄存器与BYTE,
WORD,DWORD类型的内存单元的值做比较。
image016.jpg
这里,该指令是比较的EAX和405000内存单元的值,跟之前一样,我们在OD来看看解释窗口。
image018.jpg
这个例子里面,EAX是小于405000内存单元中的值的,405000内存单元中的值是1000,相减的结果为负的,所以符号标志位S会被置1。
image020.jpg
类似的例子还有
CMP AX,WORD PTR DS:[405000]
CMP AL,BYTE PTR DS:[405000]
这两种情况下分别是与BYTE,WORD类型的内存单元的值做比较。

TEST(逻辑比较)
该指令在一定程序上和CMP指令时类似的,两个数值进行与操作,结果不保存,但是会改变相应标志位(比如说,SF,ZF,PF标志位),程序可以根据结果来决定是否跳转到相应的分支。
下面有几个例子:

TEST EAX,EAX
你会说,如果EAX与自己做比较呢?用这个指令,可以确定EAX是否等于0。
我们在OD中写入下面的指令:
TEST EAX,EAX
image022.jpg
与操作的表如下:
1 and 1 = 1
1 and 0 = 0
0 and 1 = 0
0 and 0 = 0
上表中结果为0的只有一种情况,只有当两个数都为0的情况(我们并不关心操作数的值是多少,因为我们是EAX与自身操作,它们永远是相等的),但是如果EAX的二进制某些位为1的话,那么运算的结果就不为零。
我们将EAX修改为0。
image024.jpg
OD中在寄存器上单击鼠标右键选择零。
image026.jpg
现在按下F7键。
image028.jpg
我们看到,零标志位被置1了,两个0做与操作,结果为0,所以零标志位被置1。
如果我们将EAX改为非零值,然后重复上面的操作呢。
image030.jpg
按下F7键。
image032.jpg
零标志位没有被置1的话,就说明结果不等于0。
如果你使用计算器的话,可以计算出390 AND 390结果依然是390,二进制为1110010000。
image034.jpg
因为位与运算中,如果两个操作数都为0,结果为0,如果两个操作数都为1,结果才为1,那么在这种情况,结果将依然是390,零标志位被置1。
上面是比较指令的主要部分,下面将介绍跳转指令部分。

JUMPS
所有的跳转指令都会指向程序将会跳转到的地址。我们在下面的列表中可以看到各种不同类型的跳转指令。
JMP –跳转
JE, JZ –结果为零则跳转
JNE, JNZ –结果不为零则跳转
JS –结果为负则跳转
JNS –结果不为负则跳转
JP, JPE –结果中1的个数为偶数则跳转
JNP, JNPE –结果为1的个数为奇数则跳转
JO –结果溢出了则跳转
JNO –结果没有溢出则跳转
JB, JNAE –小于则跳转 (无符号数)
JNB, JAE –大于等于则跳转 (无符号数)
JBE, JNA –小于等于则跳转 (无符号数)
JNBE, JA –大于则跳转(无符号数)
JL, JNGE –  小于则跳转 (有符号数)
JNL, JGE –大于等于则跳转 (有符号数)
JLE, JNG –小于等于则跳转 (有符号数)
JNLE, JG –大于则跳转(有符号数)

JMP
这是一个无条件跳转指令,即总是跳转到指定的地址。让我们在OD中来看一个例子:
image036.jpg
当你执行这条指令时,将跳转到401031处,然后从这里继续往下执行。
在OD中有几个选项,可以使跳转指令突出显示。
进入OPTIONS-DEBUGGINGOPTIONS:
image038.jpg
切换到CPU标签页
image040.jpg
将3个绿色阴影覆盖的复选框勾选上。
image042.jpg
可以看到现在所提供的信息更加全面与清晰了。
image044.jpg
可以看到现在OD中的红线展示了将跳转到何处,现在将跳转401031处。
按下F7键执行这条指令:
image046.jpg
EIP已经变成了401031。
image048.jpg
EIP将修改为将要跳转的地址,这里是401031。

JE或者JZ
这两个条件跳转指令是等价的,只是书写的形式不同而已。我们可以看到零标志位Z被置1则跳转。
image050.jpg
在OD中写入下面两条指令,我们验证一下是否会成功跳转,这里我们把EAX和ECX设置成相等的。
image052.jpg
我们将两操作数相减,因为两操作数相等,结果为0,零标志位Z被置1。
image054.jpg
我们来看看下面这个条件跳转:
image056.jpg
OD提醒我们零标志位Z为1,红色线显示的跳转将被执行。如果它是灰色的,那么将不会跳转。按F7键。
image058.jpg
跳转已经执行了,现在EIP是401031。
现在我们重新将EAX和ECX设置成不同的值。
image060.jpg
按下F7键,因为第一条指令的结果不为0,所以零标志位Z并不会置为1。
image062.jpg
我们继续来OD中
image064.jpg
由于跳转不会发生,所以指向箭头是灰色的。继续按F7键。
image066.jpg
可以看到跳转并没有发生,程序继续执行到了401004。这种比较指令在所有的程序中都是如此。
重复上面的例子,在跳转指令这里,但是我们暂时不执行。
image068.jpg
我们知道,零标志位Z为0,跳转不会成功。现在,我们双击零标志位Z,并修改为1看看会发生什么?
image070.jpg
可以看到跳转线变成红色了,跳转将成功执行,不管比较的结果如何,你还是可以通过直接修改标志位的值来改变跳转的流程。
我们来简要的介绍一下其他跳转的例子。

JNE或JNZ
这条指令与上面一个指令刚好相反:如果零标志位Z为0则跳转,即,要求操作的结果非零。
image072.jpg
这里我写的JNZ指令,如果EAX跟ECX相等,则零标志位Z置1。
image074.jpg
不像JZ指令,JZ指令是当零标志位Z为1时跳转,JNZ与JZ刚好相反,当零标志位为0才跳转。
可以这么理解,如果EAX跟ECX的值不同,则运算的结果将不为0,则零标志位为0,就会跳转,反过来,将不会跳转。

JS
从上面的表中可以看出,当比较的结果为负时将跳转,即,按前面的例子的话就是EAX小于ECX。
image076.jpg
按F7键:
image078.jpg
符号标志位S为1,所以将发生跳转。
image080.jpg
看到红线显示就表明将发生跳转。如果EAX大于ECX,则符号标志位S为0,结果为正,将不会发生跳转。

JNS
这个跳转指令与JS刚好相反。当零标志位S为0的时候跳转,也就是说之前例子中,EAX大于ECX的时候跳转。

JP或JPE
这个跳转指令时当奇偶标志位P置1的时候才会发生,也就是比较的结果中1的个数要是偶数。
image082.jpg
我们这里将EAX设置为20,ECX设置为18,按F7键:
image084.jpg
这里EAX与ECX的差值是2,转化为二进制是10,只有一个1,所以包含奇数个1,所以奇偶标志位为0,JPE指令就不会发生跳转。
image086.jpg
现在将ECX的值修改为17,然后按F7:
image088.jpg
可以看到结果为3,二进制形式为11,1的个数为偶数个,所以奇偶标志位置1,使用JPE指令就会发生跳转。
image090.jpg

JNP 或JNPE
这条指令刚好与上一条指令刚好相反,当奇偶标志位P为0的时候跳转。即结果中1的个数为奇数的时候。在上面的例子中,当结果为2的时候发生跳转,当结果为3的时候不会发生跳转。

JO
当发生溢出时,即溢出标志位O置1的时候跳转。
image092.jpg
这里我们需要修改一下指令,因为我们需要将溢出标志位O置位,即溢出发生,这里我们可以通过加法指令来实现。
image094.jpg
按F7键:
image096.jpg
这里跳转将执行,因为溢出标志位O被置为了1。

JNO
跟上一条指令相反,这里是当溢出标志位O为0时跳转,即溢出没有发生时。

JB
如果第一个操作数小于第二个操作数的时候跳转。这里我们来看一个例子。
image098.jpg
可以看到EAX小于ECX,所以会发生跳转。按F7键:
image100.jpg
进位/借位标志位置1,当两个操作数的差值为负的时候,该标志位将被置1,这里我们将可以得出EAX小于ECX。

JNB
和JB指令相反,这个指令是当进位/借位标志位为0的时候跳转,也就是说,结果为正的时候跳转。在前面的例子中,因为EAX小于ECX,所以不会发生跳转。

JBE
这个指令时小于或者等于的时候跳转,这是判断两个标志位的,当进位/借位标志位置1或者零标志位Z置1的时候将发生跳转,也就是说,EAX要小于或者等于ECX才会发生跳转。
image102.jpg
我们首先让EAX和ECX相等。
image104.jpg
按F7键。
image106.jpg
可以看到零标志位Z置1了。
image108.jpg
现在让EAX小于ECX:


image110.jpg
按F7键:
image112.jpg
在这种情况下, 进位/借位标志位置1,因为结果是负的,也就是说EAX小于ECX。
最后一个例子,让EAX大于ECX,然后按F7键
image114.jpg
进位/借位标志位C与零标志位Z都为0,所以跳转不会发生。
image116.jpg
也就是说,这个例子中我们要EAX小于或者等于ECX的时候才会发生跳转。

JNBE
这个指令跟JBE刚好相反,当进位/借位标志位C与零标志位Z都为0时候才会发生跳转。

JL
这个指令当小于的时候跳转,但是与前面的JB稍微有点不同。这个指令时根据符号标志位S来决定是否跳转。
来看看这样一个例子,这里EAX和ECX都是整数,并且EAX大于ECX。
image118.jpg
当你按下F7键的时候将不会发生跳转,因为EAX与ECX的差值是正数,所以符号标志位S和溢出标志位O将不会置1。
image120.jpg
还是上面的例子,这里我们让EAX小于ECX,并且两者依然是正数。
image122.jpg
按F7键:
image124.jpg
这里是操作数1小于操作数2,并且两者都是正数,所以溢出标志位O与符号标志位S不同,所以跳转将发生,我们再来看另外一个例子。
image126.jpg
这种情况下,EAX小于ECX,并且EAX为负数。看看将发生什么。
这里跳转将执行,现在我们尝试相同的值用JB指令来试试。
image128.jpg
按F7键。
image130.jpg
可以看到JB指令并不会发生跳转,因为JB比较两个数的时候,将它们两个都看做是正数,即认为它们是无符号数,但是JL指令要考虑符号,这就是这两条指令的主要区别。

image132.jpg
(此表由于是图片,就不翻译了)
可以看到,这些条件跳转指令被分为了两类:那些我们需要考虑符号的,那些不需要考虑符号的。
JA,JB,JBE,JAE的两个操作数都是正数(无符号数),而JG,JL,JLE,JGE把两个操作数都看成有符号数。


我相信,比较和条件跳转指令的介绍将凸显出它们在程序中是如何使用的。
接下来的部分将介绍call和ret指令。要多点耐性,嘿嘿。

本系列文章汉化版转载看雪论坛


感谢原作者:RicardoNarvaja(西班牙人)

原作者个人主页:http://www.ricardonarvaja.info/


感谢热心翻译的朋友:

1~3章译者:BGCoder

4~58章译者:安于此生


全集配套程序下载地址:

链接: http://pan.baidu.com/s/1eQzTWfo 密码: vytv




评分

参与人数 12HB +8 THX +6 收起 理由
花盗睡鼠 + 2 [吾爱汇编论坛52HB.COM]-软件反汇编逆向分析,软件安全必不可少!
24567 + 2
Jawon + 1
一路走来不容易 + 1
Soul1999 + 1
消逝的过去 + 1
l278785481 + 1
xgbnapsua + 1
ghostxu + 1 [吾爱汇编论坛52HB.COM]-学破解防破解,知进攻懂防守!
hackysh + 1
hnymsh + 1
lies + 1

查看全部评分

吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
Banama 发表于 2018-11-27 16:45 | 显示全部楼层

大佬您好,请问可以补一补反调试文章的链接吗,谢谢大佬了
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
头像被屏蔽
别管我了行 发表于 2022-2-28 06:40 | 显示全部楼层

提示: 作者被禁止或删除 内容自动屏蔽
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
ghostxu 发表于 2022-4-7 00:01 | 显示全部楼层
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
曾经沧海 发表于 2022-11-15 22:54 | 显示全部楼层

很实用,感谢大神分享
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
曾经沧海 发表于 2022-11-17 22:09 | 显示全部楼层
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
af521 发表于 2022-11-18 19:59 | 显示全部楼层

感谢版主的分享
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
头像被屏蔽
Wayne 发表于 2022-11-19 08:59 | 显示全部楼层

提示: 作者被禁止或删除 内容自动屏蔽
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
曾经沧海 发表于 2023-4-3 09:44 | 显示全部楼层

先顶一下,收藏好,留个脚印,下次好找
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
一生逍遥 发表于 2023-4-19 10:59 | 显示全部楼层

太棒了,感谢!
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

警告:本站严惩灌水回复,尊重自己从尊重他人开始!

1层
2层
3层
4层
5层
6层
7层
8层
9层
10层

免责声明

吾爱汇编(www.52hb.com)所讨论的技术及相关工具仅限用于研究学习,皆在提高软件产品的安全性,严禁用于不良动机。任何个人、团体、组织不得将其用于非法目的,否则,一切后果自行承担。吾爱汇编不承担任何因为技术滥用所产生的连带责任。吾爱汇编内容源于网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除。如有侵权请邮件或微信与我们联系处理。

站长邮箱:SharkHeng@sina.com
站长QQ:1140549900


QQ|RSS|手机版|小黑屋|帮助|吾爱汇编 ( 京公网安备11011502005403号 , 京ICP备20003498号-6 )|网站地图

Powered by Discuz!

吾爱汇编 www.52hb.com

快速回复 返回顶部 返回列表