jmp指令 jmp为无条件指令,可以只修改IP,也可以同时修改CS和IP. jmp指令要给出两种信息:1) 转移的目的地址2) 转移的距离(段音转移、段内转移、段内近转移) 不同的给出目的地址方法,和不同的转移位置,对应有不同格式的jmp指令. 1 依据位移进行转移的jmp指令 jmp short 标号(转到标号处执行指令) 这种格式的jmp指令实现的是段内短转移,它对IP的修改范围为-128~127,也就是说,它向前转移时可以最多超过128个字节,向后转移可以最多超过127字节. jmp指令中的”short”符号,说明指令进行的短转移. jmp指令中的”标号”是代码段中的标号,指明了指令要转移的目的地址,转移指令结束后,CS:IP应该指向标号处的指令. 程序1: 上面的程序执行后,ax中的值为1,因为执行jmp short s后,跳过了add ax, 1, IP指向标号s处的inc ax. 也就是说,程序只进行了一次ax加1操作. 汇编指令 jmp short 对应的机器指令应该是什么样的呢?我们先看一下别的汇编指令和其对应的机器指令. 可以看到,在一般的汇编指令中,汇编指令中的idata(立即数),不论它是表示一个数据还是内存单的偏移地址,都会在对应的机器指令中出现,因为CPU执行的是机器指令,它必须要处理这些数据地址. 现在我们把程序1翻译成机器码,看到的结果如图1所示:
图1 程序1的机器码 我们可以看到,Debug将jmp short s的s表示为inc ax指令的偏移地址8,并将jmp short表示为jmp 0008,表示转移到cs:0008处. 这好像挺合理,可当看与之对应的机器码,发现了一些问题. jmp 0008(Debug中的表示)或jmp short s(汇编语言中的表示)所对应的机器码为EB 03,注意,这个机器码竟不包含转移的目的地址,这表明CPU在执行EB 03时,并不知道转移的目的地址. 那么,CPU根据什么进行转移呢?它怎么知道转移去哪里呢? 汇编指令jmp short s中,明明带有转移的目的地址(由标号s表示)的, 可翻译成机器指令后,怎么目的地址就没了呢?没有目的地址,CPU如何知道转移到哪里呢? 我们把程序1稍作修改,变为程序2,如下: 我们在Debug中将程序2翻译成机器码,看到的结果如图2所示:
图2 程序2的机器码 比较程序1和程序2用Debug查看的结果,注意,两个程序中的jmp指令都要使IP指向 inc ax指令,但程序1的inc ax指令的偏移地址为8,而程序2的inc ax指令的偏移地址为000BH. 而两个程序中的jmp指令所对应的机器码都是为EB 03. 这说明CPU在执行jmp指令时不需要转移的目的地址. 也就是说,CPU不需要这个目的地址就可实现IP的修改. CPU只能处理你提供给它的东西, jmp指令的机器码码中不包含转移的目的地址,那么,CPU如何知道将IP改为多少呢?所以,在jmp指令的机器码中,一定包含了某种信息,使得CPU可以将它当做修改IP的依据. 这种信息是什么呢? 在此之前,我们来想一下CPU执行指令的过程: 1) 从CS:IP指向的内存单读取指令,读取的指令进入到指令缓冲器;2) (IP) = (IP) + 所读取指令的长度,从而指向下一条指令;3) 执行指令. 转到1,重复这个过程. 按照这个步骤,我们对照图2来看一下,程序2的jmp short s指令的读取和过程. 1) (CS) = 076Ah, (IP) = 0006h, CS:IP指向EB 03 (jmp short s的机器码);2) 读取指令EB 03f进行指令缓冲器;3) (IP) = (IP) + 所读指令的长度= 0006h + 2 = 0008h,CS:IP指向 add ax, 00014) CPU指行指令缓冲器里的指令EB 03;5) 指令EB 03执行后,(IP) = 000Bh,CS:IP指向inc ax. CPU在执行EB 03时,是根据什么修改IP,使其指向目标指令呢?就是根据指令码的03. 注意,要转移的目的地址是CS:000B,而CPU执行EB 03时,当前的(IP) = 0008h,如果将当前的IP值加3,使(IP) = 000Bh,CS:IP就可指向目标指令. 在转移指令EB 03中并没有告诉CPU要转移的目的地址,却告诉了CPU要转移的位移,即将当前IP向后移动3个字节. 由于,程序1、2中的jmp指令转移的位移相同,都是向后3个字节,所以它们的机器码都是EB 03. 原来如此,在”jmp short 标号”指令所对应的机器码中,并不包含转移的目的地址,而包含转移的位移. 这个位移,是编译器根据汇编指令中的”标号”计算出来的,具体计算方法如图3所示:
图3 转移位移的计算方法 实际上,”jmp short 标号”的功能为:(IP) = (IP) + 8位位移 1) 8位位移 = 标号处的地址 – jmp指令后的第一个字节的地址; 2) short 指明此处的位移为8位位移; 3) 8位位移的范围为 -128~127,用补码表示; 4) 8位位移由编译程序在编译时算出. 还有一种和”jmp short 标号”功能相近的指令格式:jmp near ptr 标号,它实现的是段内近转移. ”jmp near ptr 标号”的功能为:(IP) = (IP) + 16位位移. 1) 16位位移 = 标号处的地址 – jmp指令后的第一个字节的地址; 2) near ptr 指明此处的位移为16位位移,进行的是段内近转移; 3) 16位位移的范围为 -32768~32767,用补码表示; 4) 16位位移由编译程序在编译时算出. 2 转移的目的地址在指令中的jmp指令 前面的jmp指令,其对应的机器指令中并没有转移的目的地址,则是相对于当前IP的转移位移. ”jmp far ptr 标号”实现的是段间转移,又称为远转移,功能如下: (CS) = 标号所在段的段地址; (IP) = 标号在段中的偏移地址 far ptr指明了指令用标号的段地址和偏移地址修改CS和IP. 程序3: 在Debug中将程序3翻译成机器码,如图4所示:
图4 程序3的机器码 如图4所示,源程序中的db 256 dup(0),被Debug解释为相应的若干个汇编指令. 这不是重点,重点是,我们要注意一下jmp far ptr s所对应的机器码:EA 0B 01 BD 0B,其中包含转移的目的地址. “0B 01 BD 0B”是目的地址在指令中的存储顺序,高地址”BD 0B”是转移的段地址:0BBDh,低地址”0B 01″是偏移地址:010Bh. 3 转移地址在寄存器中的jmp指令 指令格式:jmp 16位reg 功能:(IP) = (16位reg) 4 转移地址在内存中的jmp指令 转移地址在内存中的jmp指令有两种格式: 1) jmp word ptr 内存单地址(段内转移) 功能:从内存单地址处开始放着一个字,是转移的目的偏移地址. 内存单可用寻址方式的任一格式给出. 如下面的指令: 执行后,(IP) = 0123h. 又比如,下面的指令: 2) jmp dword ptr 内存单地址(段间地址) 功能:从内存单地址处开始存放着两个字,高地址处的字是转移的目的段地址,低地址处的字是转移的目的的偏移地址. (CS) = (内存单地址+2)(IP) = (内存单地址) 内存单地址可用寻址方式的任一格式给出. 比如,下面的指令: 执行后,(CS) = 0, (IP) = 0123h, CS:IP指向0000:0123 又比如,下面的指令: 执行后,(CS) = 0, (IP) = 0123h, CS:IP指向0000:0123 现在,我们来看一下几个程序. 程序1: 若要使程序中的jmp指令执行后,CS:IP指向程序的第一条指令,在data段中应该定义哪些数据? 分析: 代码段中,第一条指令的IP = 0 jmp word ptr [bx+1] 属于段内转移,若jmp指令执行后,CS:IP指向程序的第一条指令,则需要保证CS不变,IP = 0,因此,只要满足内存单ds:[bx+1]的字数据为0即可. 如下: 2) 程序如下: 补全程序,使jmp指令执行后,CS:IP指向程序的第一条指令. 分析: jmp dword ptr ds:[0] 这条指令告诉我们,跳转的下一条指令的位置: (CS) = (ds:[2]), IP = (ds:[0]) 如果要保证跳转到代码段的第一条指令,需要保证内存单ds:[2]存放的字数据为CS,内存单ds:[0]存放的字数据为0. 因此,补全完的程序如下: 3) 用Debug查看内存,结果如下: 2000:1000 BE 00 06 00 00 00 … 则此时,CPU执行指令: CS = 0006h, IP = 00BEh
2024最新激活全家桶教程,稳定运行到2099年,请移步至置顶文章:https://sigusoft.com/99576.html
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。 文章由激活谷谷主-小谷整理,转载请注明出处:https://sigusoft.com/24767.html