可以修改IP,或者同时修改CS与IP的指令统称为转移指令。
因为CS:IP是指令寄存器,比较特殊,且CS无法用其他寄存器直接赋值,如:mov cs,ax。
所以需要jmp,call,ret,loop等指令来修改IP或同时修改CS与IP。
CS:IP的组合用来实现8086CPU的20位寻址(虽然8086的寄存器是16位的,但8086内部有20位地址加法器)。
另外,8086CPU是小端模式
。内存高地址存放数据高位,内存低地址存放数据低位。
转移指令种类
8086转移指令种类:
无条件转移指令(如 jmp)
条件转移指令(如 jcxz)
循环指令(如 loop)
过程(如 call、ret、retf)
中断
伪指令offset
offset 是伪指令,由汇编器识别并处理,用于取得标号的偏移地址。如:
start: mov ax,offset start ; 相当于mov ax,0
s: mov ax,offset s ; 相当于mov ax,3(因为 mov ax,0 指令占3字节)
jmp无条件转移
根据位移来转移的jmp指令
jmp short 标号,段内短转移
功能:
jmp short 标号 功能为:IP=IP+8位位移
- 8位位移=标号处的地址 - jmp指令后的第一个字节的地址;
- short 指明此处的位移为8位位移;
- 8位位移的范围是
-128~127
,用补码表示 [注1]; - 8位位移由编译程序在编译时算出。
注1:
正数的原码与反码、补码相同。负数的反码为绝对值相同的正数按位取反,补码为反码+1。
jmp near ptr 标号,段内近转移
功能:
jmp near ptr 标号 功能为:IP=IP+16位位移
- 16位位移=标号处的地址 - jmp指令后的第一个字节的地址;
- near ptr 指明此处的位移为16位位移;
- 16位位移的范围是
-32768~32767
,用补码表示; - 16位位移由编译程序再编译时算出。
段间转移、远转移jmp
jmp far ptr 标号
功能:
CS=标号所在段的段地址;IP=标号所在段的偏移地址。
如:
start: mov ax,0 ; 假设标号处段地址=0123h、偏移地址=10h
mov bx,0
jmp far ptr start ; 执行完后,CS=0123h,IP=10h
转移地址在寄存器中的jmp
jmp 16位寄存器
如:jmp ax,功能:IP=AX。
转移地址在内存中的jmp
jmp word ptr 内存单元地址
功能:
段内转移,使得 IP=内存单元地址处的一个字(占2字节)
如:
mov ax,0123h
mov ds:[0],ax
jmp word ptr [0] ; 执行后,IP=0123h
jmp dword ptr 内存单元地址
功能:
段间转移,使得 CS=内存单元地址+2 处的一个字
(2字节)、IP=内存单元地址 处的一个字
(2字节)
也就是说,内存高位的一个字给CS寄存器,内存低位的一个字给IP寄存器。
如:
mov ax,0123h
mov [bx],ax
mov word ptr [bx+2],0
jmp dword ptr [bx] ; 执行后,CS=0,IP=0123h
jcxz条件转移指令
jcxz可以理解为:Jump if CX equal Zero。
语法:jcxz 标号(如果 cx=0,转移到标号处执行)
功能:
jcxz 指令为有条件转移指令,所有有条件转移指令都是短转移,指令机器码中包含位移而不是目的地址。
- 当 cx=0 时,IP=IP+8位位移;
- 8位位移=标号处的地址 - jcxz指令后的第一个字节的地址;
- 8位位移的范围是
-128~127
,用补码表示; - 8位位移由编译程序在编译时算出。
- 当 cx ≠ 0 时,什么也不做,程序继续向下执行。
jcxz 标号 的功能相当于:
if (cx == 0) jmp short 标号
loop转移指令
语法:loop 标号(cx–,如果cx ≠ 0,转移到标号处执行)
功能:
loop 指令位循环指令,所有循环指令都是短转移,指令机器码中包含位移而不是目的地址。
操作:
cx=cx-1
如果 cx ≠ 0,IP=IP+8位位移
- 8位位移=标号处的地址 - loop指令后的第一个字节的地址;
- 8位位移的范围是
-128~127
,用补码表示; - 8位位移由编译程序在编译时算出。
- 当 cx = 0 时,什么也不做,程序继续向下执行。
loop 标号 的功能相当于:
cx--;
if (cx != 0) jmp short 标号
ret和retf转移指令
ret与retf指令
ret 指令用栈中的一个字的数据(ss:sp指向的栈),修改IP寄存器,实现近转移(段内转移)。
retf 指令用栈中的二个字的数据(ss:sp指向的栈),修改CS和IP,实现远转移(段间转移)。
功能:
ret 指令,进行如下两步操作:
- IP=SS*16 + SP 出栈,令IP=栈顶的2个字节
- SP=SP+2 栈指针指向栈中下一个字节
retf 指令,进行如下4步操作:
- IP=SS*16 + SP 栈顶2字节给IP
- SP=SP+2
- CS=SS*16 + SP 栈中接下来2字节CS
- SP= SP+2
如果用汇编语法来解释 ret 相当于:
pop IP
如果用汇编语法来解释 retf 相当于:
pop IP
pop CS
ret n 指令
ret n 的含义相当于:
pop ip
add sp,n
call转移指令
call 标号(将当前IP压栈,转到标号处执行指令)
操作:
- SP=SP-2 修改栈顶指针
- SS*16+SP=IP 当前IP的值压栈
- IP=IP+16位位移 IP加上根据标号计算出的16位位移(即段内近转移,call指令没有段内短转移)
说明:
- 16位位移=标号处的地址 - call指令后的第一个字节的地址;
- 16位位移的范围是
-32768~32767
,用补码表示; - 16位位移由编译程序在编译时算出。
call 标号 相当于:
push IP
jmp near ptr 标号
call far ptr 标号(将当前CS和IP依次压栈,转到标号处执行指令)
call far ptr 标号 实现段间转移,操作:
- sp=sp-2
ss*16+sp=CS
sp=sp-2
ss*16+sp=IP - CS=标号所在段地址
IP=标号所在段的偏移地址
call far ptr 标号,相当于:
push CS
push IP
jmp far ptr 标号
call 16位寄存器(将当前IP压栈,从寄存器获得偏移地址给IP)
功能:
sp=sp-2
ss*16+sp=IP
IP=16位寄存器
call 16位寄存器 相当于执行:
push IP
jmp 16位reg
call word ptr 内存单元地址
此指令相当于执行:
push IP
jmp word ptr 内存单元地址
如:
mov sp,10h
mov ax,0123h
mov ds:[0],ax
call word ptr ds:[0]
最后,IP=0123h,栈指针SP=0eh
call dword ptr 内存单元地址
此指令相当于执行:
push CS
push IP
jmp dword ptr 内存单元地址
如:
mov sp,10h
mov ax,0123h
mov ds:[0],ax
mov word ptr ds:[2],0
call dword ptr ds:[0]
最后,CS=0,IP=0123h,栈指针SP=0ch
cmp与根据比较结果转移的指令
先说说8086标志寄存器结构
标志寄存器在Debug程序中的表示:
算术逻辑运算相关指令:
add, sub, mul, div, inc, dec, or, and 等
传送相关指令:
mov, push, pop 等
修改标志寄存器的指令:
pushf,把标志寄存器的值入栈
popf,从栈中弹出数据放入标志寄存器
标志位含义
ZF:执行算数逻辑运算指令后,保存结果的寄存器中,结果是0,zf=1,反之zf=0
PF:执行算数逻辑运算指令后,保存结果的寄存器中,有偶数个1(0个1也是偶数)时,pf=1,奇数个1时,pf=0
SF:执行算数逻辑运算指令后,保存结果的寄存器中,符号位是1,sf=1,符号位是0,sf=0
CF:执行无符号数运算后,加法有进位或减法有借位时,cf=1,反之,cf=0
OF:执行有符号数运算后,如果有溢出(运算结果超出结果寄存器的有符号数表示范围称为溢出),of=1,否则of=0
cmp指令
cmp 是比较指令,相当于减法指令,但不会保存结果。cmp 执行后会对标志寄存器产生影响。
格式:cmp 操作对象1, 操作对象2
无符号数的cmp(涉及到标志位 ZF、CF):
有符号数的cmp(涉及到标志位 SF、OF、ZF):
根据比较结果转移的指令
这些指令与cmp配合使用,这些指令就是检测cmp执行后影响到的标志位:
根据有符号数的比较结果进行转移的条件转移指令与无符号数的原理相同,只是检查的标志位有所不同。