1、可以修改IP,或同时修改CS和IP的指令统称为转移指令。
8086CPU的转移行为有以下几类。
- 只修改IP时,称为段内转移,例如:jmp ax。
- 同时修改CS和IP时,称为段间转移,例如:jmp 1000:0。
由于转移指令对IP的修改范围不同,段内转移又分为:短转移和近转移。
- 短转移IP的修改范围为-128~127。
- 近转移IP的修改范围为-32768~32767。
8086CPU的转移指令分为以下几类。
- 无条件转移指令(如jmp)
- 条件转移指令
- 循环指令(如loop)
- 过程
- 中断
2、jmp指令
jmp为无条件转移指令,可以只修改IP,也可以同时修改CS和IP。
jmp指令要给出两种信息。
- 转移的目的地址
- 转移的距离(段间转移、段内短转移、段内近转移)
几种jmp指令:
1)jmp short 标号(转到标号处执行指令)
这种格式的jmp指令实现的是段内短转移,它对IP的修改范围是-128~127。
实际上:"jmp short 标号"的功能为:(IP)=(IP)+8位位移
- 8位位移=标号处的地址-jmp指令后的第一个字节的地址
- short指明此处的位移为8位位移
- 8位位移的范围是-128~127,用补码表示
- 8位位移由编译程序在编译时算出。
2)还有一种和"jmp short 标号"功能相近的指令格式, jmp near ptr 标号,它实现的是段内近转移。
"jmp near ptr 标号"的功能为:(IP)=(IP)+16位位移。
- 16位位移=标号处的地址-jmp指令后的第一个字节的地址
- near ptr指明此处的位移为16位位移,进行的是段内近转移
- 16位位移的范围为-32768~32767,用补码表示
- 16位位移由编译程序在编译时算出。
3)"jmp far ptr 标号"实现的是段间转移,又称为远转移。功能如下:
4)jmp 16位寄存器
功能:(IP)=(16位寄存器)
- jmp word ptr 内存单元地址(段内转移)
- jmp dword ptr 内存单元地址(段间转移)
6)jcxz指令
指令格式:jcxz 标号(如果(cx)=0, 转移到标号处执行。)
操作:当(cx)=0时,(IP)=(IP)+8位位移;
8位位移的范围为-128~127,用补码表示;
8位位移由编译程序在编译时算出。
当(cx)!=0时,什么也不做(程序向下执行)。
指令格式:loop 标号 ( (cx)=(cx)-1,如果(cx)!=0,转移到标号处执行 )
操作:
- (cx)=(cx)-1
- 如果(cx)!=0, (IP)=(IP)+8位位移。
8位位移的范围为-128~127,用补码表示;
8位位移由编译程序在编译时算出。
如果(cx)=0.什么也不做(程序向下执行)。
总结:
分析一个奇怪的程序。
assume cs:codesg codesg segment mov ax,4c00h int 21h start: mov ax, 0 s: nop nop mov di,offset s mov si,offset s2 mov ax,cs:[si] mov cs:[di],ax s0: jmp short s s1: mov ax,0 int 21h mov ax,0 s2: jmp short s1 nop codesg ends end start
程序执行顺序
mov ax,0
nop
nop
mov di,offset s
mov si,offset s2
mov ax,cs:[si]
mov cs:[di],ax
此时将s2处的代码"jmp short s1"拷贝到了s:处,刚好替换了两个nop指令的位置。
接着实行jmp short s,跳转到标号s处
执行s处替换后的代码jmp short s1,由于短转移时根据位移找指令,本来的位移是s2-s1,间距是以下代码
mov ax,0
int 21h
mov ax,0
是10个字节代码,也就是向上偏移10个字节执行。
所以此时是在s标号处向上偏移10个字节执行代码
mov ax,4c00h
int 21h
程序正常结束。