可以修改IP,或同时修改CS和IP的指令统称为转移指令。概括地讲,转移指令就是可以控制CPU执行内存中某处代码的指令。

8086CPU的转移行为有以下两类:

  • 只修改IP时,称为段内转移,比如:jmp ax
  • 同时修改CS和IP时,称为段间转移,比如:jmp 1000:0

由于转移指令对IP的修改范围不同,段内转移又分为:短转移和近转移:

  • 短转移IP的修改范围为-128~127
  • 近转移IP的修改范围为-32768~32767

8086CPU的转移指令分为以下几类:

  • 无条件转移指令(如:jmp)
  • 条件转移指令
  • 循环指令(如:loop)
  • 过程
  • 中断

一、操作符offset

操作符offset在汇编语言中是由编译器处理的符号,它的功能是取得标号的偏移地址,比如下面的程序:

assume code:codesgcodesg segmentstart:   mov ax,offset start     ;相当于mov ax,0s:   mov ax,offset s         ;相当于mov ax,3codesg endsend start

在上面的程序中,offset操作符取得了标号start和s的偏移地址0和3,因为start是代码段中的标号,它所标记的指令是代码段中的第一条指令,偏移地址为0;而s是代码段中的标号,它所标记的指令是代码段中的第二条指令,第一条指令长度为3个字节,则s的偏移地址为3

例题:

有如下的程序段,填写两条指令,使程序在运行中将s处的一条指令复制到s0处。

assume cs:codesgcodesg segments:

二、jmp指令

jmp为无条件转移指令,可以只修改IP,也可以同时修改CS和IP。jmp指令要给出两种信息:

  • 转移的目的地址
  • 转移的距离(段间转移、段内短转移、段内近转移)

不同的给出目的地址的方法,和不同的转移位置,对应有不同格式的jmp指令。

2.1 根据位移进行转移的jmp指令

jmp short 标号(转到标号处执行指令)

这种格式的jmp指令实现的是段内短转移,它对IP的修改范围为-128~127,也就是说,它向前转移时最多越过128个字节,向后转移可以最多越过127个字节。jmp指令中的“short”符号,说明指令进行的是短转移。jmp指令中的“标号”是代码段中的标号,指令了指令要转移的目的地,转移指令结束后,CS:IP应该指向标号处的指令。

比如:

程序9.1:

assume cs:codesgcodesg segmentstart: mov ax,0jmp short sadd ax,1s:   inc axcodesg endsend start

上面的程序执行后,ax中的值为1,因为执行jmp short s后,越过了add ax,1,IP指向了标号s处的inc ax。也就说,程序只进行了一次ax+1操作。

接下来我们看下汇编指令jmp short s对应的机器指令应该是什么样的,首先我们先看下别的汇编指令和其对应的机器指令:

汇编指令 机器指令
mov ax,0123h B8 23 01
mov ax,ds:[0123h] A1 23 01
push ds:[0123h] FF 36 23 01

可以看到,在一般的汇编指令中,汇编指令中的idata(立即数),不论它是表示一个数据还是内存单元的偏移地址,都会在对应的机器指令中出现,因为CPU执行的是机器指令,它必须要处理这些数据或地址。

将程序9.1翻译成机器码,得到的结果如下所示:

对照汇编程序,我们可以看到,Debug将jmp short s中的s表示为了inc ax指令的偏移地址8,并将 jmp short s表示为jmp 0008,表示转移到cs:0008处。这一切似乎合理,可是当我们查看jmp short s或是jmp 0008所对应的机器码,却发现了一些问题。

jmp 0008或jmp short s所对应的机器码为 EB 03,注意,这个机器码中不包含转移的目的地址,这意味着,CPU在执行EB 03的时候,并不知道转移的目的地址。

所以CPU在执行EB 03的时候是根据什么修改的IP,使其指向目标指令呢?就是根据指令码中的03。注意,要转移的目的地址是CS:0008,而CPU执行EB 03时,当前的(IP)=0005H,如果将当前的IP值加3,使(IP)=0008H,CS:IP就可指向目标指令。在转移指令EB 03中并没有告诉CPU要转移的目的地址,却告诉了CPU要转移的位移,即将当前的IP向后移动3个字节。

转移的位移是编译器根据汇编指令中的”标号“计算出来的,方法如下所示:


实际上,”jmp short 标号“的功能为:(IP)=(IP)+8位位移

  • 8位位移=标号处的地址-jmp指令后的第一个字节的地址
  • short指明此处的位移为8位位移
  • 8位位移的范围为-128~127,用补码表示
  • 8位位移由编译程序在编译时算出

还有一种和"jmp short 标号"功能相近的指令格式,jmp near ptr 标号,它实现的是段内近转移。

"jmp near ptr 标号"的功能为:(IP)=(IP)+16位位移

  • 16位位移=标号处的地址-jmp指令后的第一个字节的地址
  • near ptr指明此处的位移为16位位移,进行的是段内近转移
  • 16位位移的范围为-32768~32767,用补码表示
  • 16位位移由编译程序在编译时算出

2.2 转移的目的地址在指令中的jmp指令

前面所讲的jmp指令,其对应的机器指令中并没有转移的目的地址,而是相对于当前IP的转移位移。

”jmp far ptr 标号“实现的是段间转移,far ptr指明了指令用标号的段地址和偏移地址修改CS和IP。

看下面的程序:

程序9.3

assume cs:codesgcodesg segmentstart: mov ax,0mov bx,0jmp far ptr sdb 256 dup (0)s:   add ax,1inc axcodesg ends
end start

在Debug中将程序9.3翻译成机器码,看到的结果如下所示:

如上图所示,源程序中的db 256 dup (0),被Debug解释为相应的若干条汇编指令。这不是关键,关键是,我们要注意一下jmp far ptr s所对应的机器码:EA 0B 01 D2 1C,其中包含转移的目的地址。"0B 01 D2 C1"是目的地址在指令中的存储顺序,高地址的"D2 1C"是转移的段地址:1CD2H,低地址的"0B 01"是偏移地址010BH。

2.3 转移地址在寄存器中的jmp指令

指令格式:jmp 16位 reg
功能:(IP)=(16位reg)

2.4 转移地址在内存中的jmp指令

转移地址在内存中的jmp指令有两种格式:

jmp word ptr 内存单元地址(段内转移)

功能:从内存单元地址处开始存放着一个字,是转移的目的偏移地址。

内存单元地址可用寻址方式的任一格式给出。

比如,下面的指令:

mov ax,0123H
mov ds:[0],ax
jmp word ptr ds:[0]

执行后,(IP)=0123H

又比如,下面的指令:

mov ax,0123H
mov [bx],ax
jmp word ptr [bx]

执行后,(IP)=0123H

jmp dword ptr 内存单元地址(段间转移)

功能:从内存单元地址处开始存放着两个字,高地址处的字是转移的目的段地址,低地址处是转移的目的偏移地址。

(CS)=(内存单元地址+2)
(IP)=(内存单元地址)

内存单元地址可用寻址方式的任一格式给出。

比如,下面的指令:

mov ax,0123H
mov ds:[0],ax
mov word ptr ds:[2],0
jmp dword ptr ds:[0]

执行后,(CS)=0,(IP)=0123H,CS:IP指向0000:0123

又比如,下面的指令:

mov ax,0123H
mov [bx],ax
mov word ptr [bx+2],0
jmp dword ptr [bx]

执行后,(CS)=0,(IP)=0123H,CS:IP指向0000:0123

例题:

程序如下:

assume cs:codedata segment?
data endscode segmentstart: mov ax,datamov ds,axmov bx,0jmp word ptr [bx+1]code endsend start

若要使程序中的jmp指令执行后,CS:IP指向程序中的第一条指令,在data段中应该定义哪些数据?

答案:

注意这里offset start=0,所以只需要[bx+1]内存处存储0即可,所以答案可以是db 0,0,0

三、jcxz指令

jcxz指令为有条件转移指令,所有的有条件转移指令都是短转移,在对应的机器码中包含转移的位移,而不是目的地址。对IP的修改范围都为-128~127

指令格式, jcxz 标号(如果(cx)=0,转移到标号处执行)

操作:当(cx)=0时,(IP)=(IP)+8位位移

  • 8位位移=标号处的地址-jcxz指令后的第一个字节的地址
  • 8位位移的范围为-128~127,用补码表示
  • 8位位移由编译程序在编译时算出

当(cx)≠\ne​= 0时,什么也不做(程序向下执行)。

我们从jcxz的功能可以看出,“jcxz 标号”的功能相当于:

if((cx)==0) jmp short 标号

例题:

利用jcxz指令,实现在内存2000H段中查找第一个值为0的字节,找到后,将它的偏移地址存储在dx中。

assume cs:codecode segmentstart: mov ax,2000Hmov ds,axmov bx,0s: ________________________________jmp short sok:  mov dx,bxmov ax,4c00hint 21hcode endsend start

答案:

mov ch,0
mov cl,[bx]
jcxz ok
inc bx

四、loop指令

loop指令为循环指令,所有的循环指令都是短转移,在对应的机器码中包含转移的位移,而不是目的地址。对IP的修改范围都是-128~127

指令格式:loop 标号

操作:

  1. (cx)=(cx)-1
  2. 如果(cx)≠\ne​= 0,(IP)=(IP)+8位位移

注意:

  • 8位位移=标号处的地址-loop指令后的第一个字节的地址
  • 8位位移的范围为-128~127,用补码表示
  • 8位位移由编译程序在编译时算出

如果(cx)=0,什么也不做(程序向下执行)

我们从loop的功能中可以看出,“loop 标号”的功能相当于:

(cx)--
if((cx)!=0) jmp short 标号

五、根据位移进行转移的意义

前面我们讲到:

jmp short 标号
jmp near ptr 标号
jcxz 标号
loop 标号

等几种汇编指令,它们对IP的修改是根据转移目的地址和起始地址之间的位移来进行的。在它们对应的机器码中不包含转移的目的地址,而包含的是到目的地址的位移。

这种设计,方便了程序段在内存中的浮动装配。

例如:

 汇编指令                机器代码mov cx,6            B9 06 00mov ax,10h          B8 10 00
s:  add ax,ax           01 C0loop s             E2 FC

这段程序装在内存中的不同位置都可正确执行,因为loop s在执行时只涉及s的位移,而不是s的地址。如果loop s的机器码中包含的是s的地址,则就对程序段在内存中的偏移地址有了严格的限制,因为机器码中包含的是s的地址,如果s处的指令不在目的地址处,程序的执行就会出错。而loop s的机器码中包含的是转移的位移,就不存在这个问题了,因为,无论s处的指令的实际地址是多少,loop指令的转移位移是不变的。

六、编译器对转移位移超界的检测

注意,根据位移进行转移的指令,它们的转移范围收到转移位移的限制,如果在源程序中出现了转移范围超界的问题,在编译的时候,编译器将报错。

比如,下面的程序将引起编译错误:

assume cs:codecode segmentstart: jmp short sdb 128 dup (0)s: mov ax,0ffffhcode endsend start

jmp short s的转移范围是-128~127,IP最多向后移动127个字节。

分析一个奇怪的程序:

分析下面的程序,思考下这个程序是否可以正确返回。

assume cs:codesgcodesg segmentmov ax,4c00hint 21hstart:  mov ax,0s:  nopnopmov di,offset smov si,offset s2mov ax,cs:[si]mov cx:[di],axs0:    jmp short ss1:  mov ax,0int 21hmov ax,0s2:  jmp short s1nopcodesg endsend start

答案:

可以正常返回,jmp short s1的机器码是EBF6,即使得当前的IP=IP-10,将这条指令移动到s处后,jmp short s1不会指向s1了,而是知道相对当前位置-10的位置,即mov ax,4c00h,所以这个程序可以正确返回。

四、汇编JCC指令表

JCC指条件跳转指令,CC就是指条件码

JCC指令 中文含义 英文原意 检查符号位 典型C应用
JZ/JE 若为0则跳转;若相等则跳转 jump if zero/equal ZF=1 if(i==j);if(i==0)
JNZ/JNE 若不为0则跳转;若不相等则跳转 jump if not zero/equal ZF=0 if(i!=j);if(i!=0)
JS 若为负则跳转 jump if sign SF=1 if(i<0)
JNS 若为正则跳转 jump if not sign SF=0 if(i>0)
JP/JPE 若1出现次数为偶数则跳转 jump if Parity(Even) PF=1 (null)

待补充

9-汇编转移指令-offset+jmp+jcc+loop相关推荐

  1. 【汇编】转移指令——offset 标号、jmp无条件转移,段内/段间转移区别、段内近转移/段内短转移、jcxz指令、loop指令

    多种转移指令详解 9.1 转移 综述 9.2 offset 标号 9.3 jmp指令 段内/段间转移区别 段内短转移与近转移 jmp小结 9.4 jcxz 9.5 loop 9.1 转移 综述 转移按 ...

  2. c语言中offset用法,offset的使用 汇编中OFFSET的用法和所指内容

    offset在C语言中使用是什么意思啊?? 请教 Excel VBA Range.offset 的用法 Range.Offset 属性 返回 Range 对象,它代表位于指定单元格区域的一定的偏移量位 ...

  3. 汇编中的jmp转移指令:jmp short、jmp near ptr、jmp far ptr

    从8086CPU的定义上来讲,只要是可以修改IP(指令指针寄存器),或同时修改CS(代码段寄存器)和IP(指令指针寄存器)的指令统称为转移指令.也就是说,转移指令是用来控制CPU指向内存中某处代码的指 ...

  4. 汇编语言JMP和LOOP(转移)指令

    默认情况下,CPU 是顺序加载并执行程序.但是,当前指令有可能是有条件的,也就是说,它按照 CPU 状态标志(零标志.符号标志.进位标志等)的值,把控制转向程序中的新位置. 汇编语言程序使用条件指令来 ...

  5. 基于8086CPU微处理器的汇编学习之JMP指令

    JMP指令: 更改CS:IP寄存器的内容,以让CPU从新指定的内存地址开始继续执行指令. 格式: JMP  段地址:偏移地址 ------------------------------------- ...

  6. 贺利坚老师汇编课程25笔记:LOOP指令看CX

    用CX和LOOP指令相配合实现循环功能的三个要点 1.在CX中存放循环次数 2.用标号指定循环开始的位置 3.在标号和LOOP指令的中间,写上要循环执行的程序段(循环体) 代码计算2^12 ;loop ...

  7. 汇编笔记五【JCC】 by:凉游浅笔深画眉 / Net7Cracker

    一.JMP指令:无条件跳转指令,本质是修改EIP的值,改变CPU运行路线 MOV EIP,寄存器/立即数 简写为 JMP 寄存器/立即数 二.CALL指令: PUSH 地址B MOV EIP , 地址 ...

  8. 贺利坚老师汇编课程26笔记:LOOP指令使用再议

    计算FFFF:0006字节单元中的数乘以3,结果存储在DX中 思路:先将内存中数据取出,连加3次 代码 ASSUME CS:CODE CODE SEGMENTMOV AX,0FFFFH;常识:不能以字 ...

  9. 汇编语言的预习和复习

    目录 编译环境 计算机中的数据表示 二进制.十进制.十六进制 ASCII码表 计算机中的数据表示 无符号数的表示 有符号数的表示 8086微处理器 CPU 寄存器 8086寻址 数据传送指令 mov ...

  10. 与数据相关的运算符和伪指令 offset align ptr type lengthof sizeof label 间接寻址 间接操作数 数组 变址操作数 指针 jmp, loop

    与数据相关的运算符和伪指令 offset 数据标号的偏移量,按字节计算,表示数据标号到数据段开始的距离 .data bVal byte ? wVal word ? dVal dword ? dVal2 ...

最新文章

  1. Stas and the Queue at the Buffet
  2. gulp + webpack 构建多页面前端项目 1
  3. 本周两场直播丨通过源码了解openGauss多线程架构;Oracle数据库索引分裂详解。...
  4. vue给组件传html,如何将 html 模板作为道具传递给 Vue 组件
  5. oracle 01035,oracle常用命令(一)
  6. WP开发笔记——页面传参
  7. 吴恩达机器学习视频笔记和编程作业(Python实现)汇总
  8. VC2005项目属性配置
  9. mysql定时导出数据_mysql定时备份数据
  10. idea中html导入背景图片,Intellij IDEA代码框使用自定义背景图片
  11. 解决应用程序错误,内存不能为“read”或“written”
  12. 中国农业银行计算机专业笔试题,中国农业银行笔试题库
  13. jenkins+svn+脚本实现CIDI
  14. js 修改meta标签 属性
  15. python打开ie浏览器_python+selenium启动IE浏览器
  16. ConvLSTM-AE for VAD (ICME2017-SIST)
  17. 高数_第6章无穷级数_幂级数之__阿贝尔定理
  18. ubuntu查看 固态硬盘位置_在Ubuntu(Linux)中启用固态硬盘(固态硬盘)TRIM | MOS86...
  19. iPhone 14连夜跌至4800元,现在应该直接入手14,还是等15?
  20. 感恩节快到了 Thanksgiving is coming,愿所有人健康平安!

热门文章

  1. ENVI Flaash大气校正与6S大气校正(TM为例)
  2. ArcGIS中属性域的使用
  3. Homestead安装 PHP Redis 扩展
  4. StringUtils测试
  5. java 30天之前,Java获取当前时间30天之前的时间
  6. java 悬浮提示框_弹出提示框的方式——java
  7. 卧槽,又来一个 Java 神器!!
  8. 你是否真的适合搞NDK开发?
  9. python面向对象——类(上)
  10. php实现观看记录,PHP实现浏览历史记录