段内转移和段间转移

转移指令:控制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

程序如下图:

jmp用法以及原理分析-编程知识网

看下例程序和上面的程序的不同点

程序一:

assume cs:code
code segmentstart:mov ax,0jmp short sadd ax,1s:inc ax	mov ax, 4c00hint 21h		
code endsend start

jmp用法以及原理分析-编程知识网

程序二:

assume cs:code
code segmentstart:mov ax,0mov bx,1jmp short sadd ax,1s:inc ax 	mov ax, 4c00hint 21h	
code endsend start

jmp用法以及原理分析-编程知识网

这两个程序中用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用法以及原理分析-编程知识网

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用法以及原理分析-编程知识网


其他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位位移