这一章主要介绍了转移指令jmp的实现原理,个人感觉还是比较重要的一章,这一章就详细摘录书上的例题及练习,已达到巩固的效果。
offset是由编译器执行的指令并没有对应的机器码。
语法:offset 标号
功能:获取标号的偏移地址
书上的例子
1 ;offset 2 3 assume cs:codesg 4 5 codesg segment 6 7 start: mov ax,offset start 8 s: mov ax,offset s 9 10 mov ax,4c00h 11 int 21h 12 13 14 codesg ends 15 end start
可以看到,标号offset偏移地址为0它是第一条指令,标号s的偏移地址为3,这是因为mov ax,offset start占用了三个字节。
转移指令是指可以修改IP,或同时修改IP和CS的指令。
段内转移:只修改IP的值,又分为短转移和近转移。短转移是值IP的修改范围在-128~127之间(内存单元的储值范围),近转移是指IP的修改范围在-32768~32767(寄存器的储值范围)之间。
段间转移:同时修改CS和IP的值。
jmp指令的格式(目前所学):
1.jmp short 标号:段内短转移
2.jmp near ptr 标号:段内近转移
3.jmp far ptr 标号:段间转移
4.jmp 寄存器:段内转移
5.jmp word ptr 内存单元:段内转移
6.jmp dword ptr 内存单元:段间转移
书上的例子
1 ;jmp short 标号 2 3 assume cs:codesg 4 5 codesg segment 6 7 start: mov ax,0 8 jmp short s 9 add ax,2 10 s: inc ax 11 12 mov ax,4c00h 13 int 21h 14 15 16 codesg ends 17 end start
从上图可以看出,jmp short s已被翻译成jmp 0008即jmp标号s的偏移地址,而对应的机器码为EB03。
jmp short s执行时不需要目的地的地址,只需要应转移的位移即可,过程是这样的:
1.(CS)=076AH,(IP)=0003H,CS:IP指向jmp short s(EB03)
2.读取指令EB03至指令缓冲器,(ip)=(ip)+2(加2是因为jmp short s指令长度为2字节),(ip)=0005H
3.执行指令EB03向后3个字节,(ip)=(ip)+3,(ip)=0008H
这是向后转移的例子,我们再来做个向前转移的例子
1 ;jmp short 标号 2 3 assume cs:codesg 4 5 codesg segment 6 7 start: mov ax,0 8 s: inc ax 9 add ax,2 10 jmp short s 11 12 mov ax,4c00h 13 int 21h 14 15 codesg ends 16 end start
jmp short s这次过程是这样的:
1.(CS)=076AH,(IP)=0007H,CS:IP指向jmp short s(EBFA)
2.读取指令EBFA至指令缓冲器,(ip)=(ip)+2(加2是因为jmp short s指令长度为2字节),(ip)=0009H
3.执行指令EBFA向前6个字节,(ip)=(ip)-6,(ip)=0003H
EBFA表示向前6个字节由补码解释,6H=00000110B,取反+1为11111010B=FAH,有以上两个程序可知jmp指令的位移等于标号处的偏移地址-jmp指令的下一条指令的偏移地址,看上去挺绕的,减去下一条指令的地址是因为在CPU执行指令前先将ip加上jmp的指令长度,所以要减去jmp指令的长度。
jmp short s只可以转移-128~127的范围那超出会怎样呢?试下就知道了
1 ;jmp short 标号 2 3 assume cs:codesg 4 5 codesg segment 6 7 start: mov ax,0 8 jmp short s 9 db 128 dup(1) 10 s: inc ax 11 12 mov ax,4c00h 13 int 21h 14 15 codesg ends 16 end start
很明显,编译时报错超出1字节
jmp near ptr和jmp short 功能相似只不过范围变成了-32768~32767
(CS)=标号所在段的段地址,(ip)=标号在段中的偏移地址
1 ;jmp far ptr 标号 2 3 assume cs:codesg 4 5 codesg segment 6 7 start: mov ax,0 8 jmp far ptr s 9 db 128 dup(1) 10 s: inc ax 11 12 mov ax,4c00h 13 int 21h 14 15 codesg ends 16 end start
机器码EA88006A07,其中低位8800偏移地址,高位6A07为段地址即(cs)=076AH,(IP)=0088H.
8086COU是16位寄存器,所以jmp 寄存器所能转移的范围为-32768~32767,属于段内转移。
word是字型数据占2个字节,所以能转移的范围为-32768~32767,属于段内转移,将内存单元开始的字型数据赋给IP。
dword是双字型数据占4个字节,所以高地址处的字型数据是段地址,低地址处的字型数据是偏移地址。
1 ;jmp dword ptr 2 3 assume cs:codesg 4 5 codesg segment 6 7 start: mov ax,0123h 8 mov ds:[0],ax 9 mov bx,0 10 mov ds:[2],bx 11 jmp dword ptr ds:[0] 12 13 mov ax,4c00h 14 int 21h 15 16 codesg ends 17 end start
jcxz 标号表示当cx等于0时转移到标号处执行。
if((cx)==0)
jmp short 标号