转移指令

转移指令

修改IP,或者同时修改CS和IP的指令系统称为转移指令

内转移

只修改IP时,称为段内转移,比如:jmp ax

段间转移

同时修改CS和IP时,称为段间转移, 比如:jmp 1000:0

短转移

只修改IP的转移,范围为-128~127

近转移

只修改IP的转移,范围为:-32768~32767

转移指令的分类

  • 无条件转移指令
  • 条件转移指令
  • 循环指令
  • 过程
  • 中断

操作符offset

取得标号的偏移地址

例如:

assume cs:codesg
codesg segment
	start:
		mov ax, offset start
	s:
		mov ax, offset s
codesg ends
endstart

nop

机器码占用一个字节

根据位移进行转移的jmp指令,short

jmp short 标号(转到标号处执行指令) (IP) = (IP) - 8位位移

  • 8位位移=标号处的地址-jmp指令后的第一个字节的地址
  • short指明此处的位移为8位位移
  • 8位位移由编译程序在编译时算出

jmp 标号的机器码可以手动算出来,比如下面的例子

assume cs:codesg
codesg segment
	start:
		mov ax, offset start
	s:
		mov ax, offset s
		jmp short start  ; 对应的机器码就为 当前语句的IP地址 - start的IP地址,然后转换为补码
codesg ends
endstart

jmp near ptr 标号

它实现的是段内近转移

  1. 16位位移 = 标号处的地址-jmp指令后的第一个字节的地址
  2. near ptr指明此处的位移位16位位移,进行的是段内近转移
  3. 16位位移的范围为-32767~32767
  4. 16位位移由编译程序在编译时算出

jmp short 标号jmp near ptr都是相对于当前IP的转移位移

jmp far ptr 标号实现的是段间转移,又称为远转移

  • CS = 标号所在段的段地址
  • IP = 标号在段中的偏移地址
  • far ptr 指明了用标号的短地址和偏移地址修改CS和IP

指令的地址在寄存器中jmp 16位reg

jmp 16位reg

功能:IP = 16位REG

转移地址在内存中的指令jmp word ptr 地址|[bx|idata]

从内存单元地址处开始存放着一个字,是转移的目的偏移地址

例如:

mov ax, 0123h
mov ds:[0], ax
jmp word ptr ds:[0]

执行后IP= 0123h

又比如

mov ax, 0132h
mov [bx], ax
jmp word ptr [bx]

执行后IP= 0123H

jmp dwrod ptr内存单元地址(段间转移)

功能:从内存单元地址处开始存放着两个字,高地址处的字是转移的目的段地址,低地址处是转移的目的偏移地址。

  • CS = 内存单元地址 + 2
  • IP = 内存单元地址

例如:

mvo ax, 0123h
mov ds:[0], ax
mov word ptr ds:[2], 0
jmp dword ptr ds:[0]

执行后,CS = 0, IP= 0123H,CS:IP指向0000:0123

又比如

mov ax, 0123h
mov [bx], ax
mov word ptr [bx + 2], 0
jmp dword ptr [bx]

执行后:CS = 0, IP = 0123H, CS:IP指向:0000:0123

条件转移指令 jcxz

jcxz为有条件转移指令,所有的条件转移指令都是短转移,在对应的机器码中包含转移的位移,而不是目的地址。对IP的修改范围为-128-127

指令格式: jcxz 标号(如果(cx)=0,转移到标号处执行)

操作:当(cx)=0时,(IP)=(IP) + 8 位位移

8位位移=标号处的地址-jcxz指令后的第一个字节地址

8位位移的范围为-128-127,用补码表示

8位位移由编译程序在编译时算出

jcxz 标号相当于

if ((cx) == 0) jmp short 标号;

例如:

assume cs:code

data segment
	db 1, 1, 1, 0
data ends
code segment
	start:
		mov ax, data
		mov ds, ax
		mov bx, 0
	s:
		mov cx, [bx]
		jcxz ok ; 判断cx是否为0
		inc bx
		jmp short s
	ok:
		mov dx, bx
		mov ax, 4c00h
		int 21h
code ends

end start

loop指令

loop指令为循环指令,所有的循环指令都是短转移, 在对应的机器码中包含转移的位移,而不是目的地址。对IP的修改范围为:-128~127

指令格式: loop 标号((cx) = (cx) - 1, 如果(cx)不等于0,则转移到标号处执行)

指令相当于

(cx)--
if ((cx) != 0) jmp short 标号

根据位移的指令

  1. jmp short 标号
  2. jmp near ptr 标号
  3. jcxz 标号
  4. loop 标号

位移如果复制到其他地方执行,一定要考虑好距离,否则会发生乱跳的结果

他们对IP的修改是根据转移目的地址和转移其实地址之间的位移来进行的。他们对应的机器码中不包含转移的目的地址,而包含的是目的地址的位移。这样设计,方便了程序段在内存中的浮动装配。

CALL 和 RET 指令

ret指令用栈中的数据,修改IP的内容,从而实现 近转移

CPU执行RET指令的时候需要进行两步操作

  1. (IP)=((ss) * 16 + (SP))
  2. (sp) = (sp) + 2

相当于执行

POP IP

retf指令用栈中的数据,修改CS和IP的内容,从而实现远转移

CPU在执行retf指令时,进项下面4步操作

  1. (IP) = ((SS) * 16 + (SP))
  2. (SP) = (SP) + 2
  3. (CS) = ((SS) *16 + (SP))
  4. (SP) = (SP) + 2

相当于执行

pop IP
pop CS

call 指令

CPU执行call指令时,进行两部操作

  1. 将当前的IPCSIP压入栈中
  2. 转移

注意:

  • call指令不能实现短转移
  • call和jmp指令的原理相同

依据位移进行转移的call指令

call 标号(将当前的IP压栈后,转到标号处执行指令)

CPU执行此种格式的CALL指令时,进行如下操作

  1. (SP) = (SP) - 2
  2. ((SS) * 16 + (SP)) = (IP)
  3. (IP) = (IP) + 16位位移

16位位移 = 标号处的地址 - call指令后的第一个字节的地址

16位位移的范围为-32768~32767, 用补码表示

16位位移由编译程序在编译时算出

call 标号相当于执行

push IP
jmp near ptr 标号

转移的目的地址在指令中的call指令

语法

call far ptr 标号

CPU执行此种格式的call指令时,进行如下操作

  1. (SP) = (SP) - 2
  2. ((SS) * 16 + (SP)) = (CS)
  3. (SP) = (SP) - 2
  4. ((SS) * 16 + (SP)) = (IP)
  5. (CS) = 标号所在段的段地址
  6. (IP) = 标号在段中的偏移地址

CPU执行call far ptr 标号时, 相当于进行

  1. PUSH CS
  2. PUSH IP
  3. jmp far ptr 标号

转移地址在寄存器中的call指令

指令格式:call 16位reg

CPU执行此种格式的call指令时,进行如下操作

  1. (sp) = (sp) - 2
  2. ((ss) * 16 + (SP) = (IP))
  3. (IP) = (16位reg)

相当于执行了

push IP

jmp 16位reg

转移地址在内存中的call指令

两种格式

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 内存单元地址

用汇编语法来解释此种格式的call指令,则:

CPU执行call dword ptr 内存单元地址时相当于执行:

  1. push CS
  2. push IP
  3. 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

原文地址:https://www.cnblogs.com/songyaqi/p/11887938.html