段内转移和段间转移
转移指令:控制cpu执行内存中的某行代码,可以通过修改IP或者同时修改cs:ip
只修改IP的称为段内转移:jmp ax 相当于 mov ax,ip jmp ax
同时修改cs:ip的叫段间转移:jmp 1000:0(这是debug语法,只能在debug中使用)
段内转移分为短转移和近转移
短转移ip修改范围:-128-127(一个有符号的字节范围)
近转移ip修改范围:-32768-32767(两个有符号字节范围)
8086转移指令分几类:
无条件转移指令:如jmp
条件转移指令:如jcxz
循环指令:如loop
过程
中断
操作符offset:
操作符offset在汇编语言中是由编译器处理的符号,它的功能是获取标号的偏移地址IP,如下程序
assume cs:code
code segmentstart:mov ax offset start ;相当于mov ax 0(start)s: mov ax offset s ;相当于mov ax 3(s)mov ax, 4c00hint 21h
code endsend start
Jmp的转移指令原理
一般在汇编指令中,汇编指令中的idata,不论它是表示一个数,还是内存单元地址都会在对应的机器码中出现,因为cpu执行的是机器指令,它必须处理这些数据和或地址,如下程序
assume cs:code
code segmentstart:mov ax,0mov bx,0123mov ax,ds:[0123H]push ds:[0123h] mov ax, 4c00hint 21h;code ends
end start
程序如下图:
看下例程序和上面的程序的不同点
程序一:
assume cs:code
code segmentstart:mov ax,0jmp short sadd ax,1s:inc ax mov ax, 4c00hint 21h
code endsend start
程序二:
assume cs:code
code segmentstart:mov ax,0mov bx,1jmp short sadd ax,1s:inc ax mov ax, 4c00hint 21h
code endsend start
这两个程序中用jmp short命令编译后的目的地址(idata)没有出现在机器码中,这说明cpu在执行jmp转移指令的时候不需要目的地址
那cpu是靠什么进行转移到目的地址的呢?
回想cpu执行指令的过程:
1从cs:ip处向内存单元读取指令,指令进入缓冲区
2ip=ip+指令的长度,cpu指向下一条指令
3执行指令,重复步骤1继续循环
用cpu执行指令过程分析程序1的jmp指令:
1cs=0B41 ip=0003,cpu指向EB03机器码
2从内存单元0B41:0003处读取指令EB03, EB03进入缓冲区
3ip=0003+2=0005,cpu指向add ax,1
4cpu执行指令缓冲区的EB03
5EB03执行后ip=0008,cs:ip指向inc ax
在这个过程中可以分析得出,cpu执行指令前ip=0005指向add ax,1,但是执行EB03后,ip=0008cpu指向inc ax,cpu是根据EB03而判断执行下一条指令的,
EB03是根据是什么修改ip(偏移地址)的,让cpu转移到目标地址的呢?是根据EB03中的03修改ip,要转移的目标指令cs:0008,当前ip=0005,ip=ip+3=0008
这时cpu就指向目标地址了,在转移指令EB03并没有告诉cpu转移的目的地址却告诉的cpu要转移的位移,即将当前的ip向后移动3个字节,程序1和2中jmp指令的位移都相同所以它们的机器码都是EB 03
从上面可以知道机器码中包含的信息是转移的位移,而位移是在由编译器在编译的时候根据标号算出位移的
如图表示位移计算:
jmp short 标号 功能为:段内短转移 (IP)=(IP)+8位位移
1 8位位移=标号处的地址-jmp指令后的第一个字节地址
2 short指明的此处是8位位移
3 8位位移的范围为-128-127,用补码表示
4 8位位移是编译程序时在编译时算出的
jmp near ptr 标号 功能为:段内近转移 (IP)=(IP)+16位位移
1 8位位移=标号处的地址-jmp指令后的第一个字节地址
2 short指明的此处是8位位移
3 8位位移的范围为-32768-32767,用补码表示
4 8位位移是编译程序时在编译时算出的
下面用jmp指令举一个有意思的程序如下:
assume cs:code
code segmentmov ax,4c00hint 21h
start: mov ax,0s: nop ;jmp short s1 (EBF6)nopmov di,offset s ;offset获取s标号的偏移地址mov si,offset s2mov ax,cs:[si] ;cs:[si]是s2的偏移地址的内存空间,里面的值是jmp short s1mov cs:[di],ax ;把jmp short s1放到cs:[di]=cs:[s]的地址内存空间s0: jmp short s;看图解释如下:;这时转移到s偏移地址执行,s处是jmp short s1,在编译的时候偏移地址;就已经算好了是-10(f6),所以执行时候从s处执行jmp short s1(EBF6)时;目的地址=当前ip(000A)+偏移地址(-10),jmp就转移的目的地址是cs:00处;执行cs:00处mov ax,4cooh程序运行结束s1: mov ax,0int 21hmov ax,0s2: jmp short s1 ;执行时偏移地址为-10 补码=f6nopcode ends
end start
程序实验如下图:
其他jmp转移指令
jmp far ptr 标号 功能为:段间转移,far ptr指明了用标号的段地址(CS)和偏移地址(IP)修改CS:IP,让cpu指向目的地址,这是直接给出目的地址,不是根据位移
jmp word ptr 内存单元地址 功能为:段内转移 从内存单元处开始存放着一个字,是转移的目的偏移地址
jmp dword ptr 内存单元地址 功能为:段间转移 从内存单元处开始存放着两个字,高地址字是转移的目的段地址,低地址处放转移的目的偏移地址
jcxz 标号(条件转移)功能为:当(cx)=0时,(ip)=(ip)+8位位移,当(CX)!=(不等于)0时候,什么也不做,程序向下执行,
JCXZ 标号相当于 if(cx==0) { jmp short 标号 }
LOOP和JCXZ相反,当CX!=0时,(IP)=(ip)+8位位移