Skip to content

Latest commit

 

History

History
444 lines (281 loc) · 9.34 KB

File metadata and controls

444 lines (281 loc) · 9.34 KB

第19节 流程转移和子程序

❤️💕💕汇编语言目前仍在发挥着不可替代的作用,在效率上无可替代,在底层,学习linux内核,计算机外围设备和驱动,都离不开汇编。Myblog:http://nsddd.top


[TOC]

转移

在一般情况下,指令是按照循序逐条运行的,我们称之为这样的指令为静态指令。

而在实际中,经常需要改变程序的执行流程,此时的指令我们称之为动态指令。

mov ax, 0
jmp short s
add ax ,1 	;不执行,跳过
s: inc ax

转移指令

  • 可以控制CPU执行内存中某处的指令
  • 可以修改IP,或者同时修改CS和IP的指令

转移指令的分类

按照转移行为分类:

  • 段内转移:只修改IP,不修改CS jmp ax
  • 段间转移:同时修改CS和IP jmp 1000:0

按照指令对IP修改的范围不同:

  • 段内短转移:IP修改范围为-128~127 (八位 – 1个字节)
  • 段内近转移:IP修改范围为-32768~32767 (十六位 – 2个字节 – 1个字)

按照转移指令分类:

  • 无条件转移指令:jmp
  • 带条件转移指令:jcxz
  • 循环指令:loop
  • 过程
  • 中断

offset

格式

offset 标号

案例

assume cs:codeseg
codeseg segment
start:	;start开始的位置  - 0
	mov ax, offset start	;相当于:mov ax, 0
	s:	;s的地址是3,ax是三个字节指令
	mov ax, offset s		;相当于:mov ax, 3
codeseg ends
end start

jmp指令

jmp指令功能

无条件转移,可以只修改IP,可以同时修改IP和CS

  1. 短程转移(直接短转移)
指令格式:JMP SHORT OPRD
语法格式:JMP 地址标号 ;(IP)=(IP)+8位位移量

指令功能:

  • OPRD为转移地址的标号,指令中的SHORT规定了OPRD为有符号的8位二进制数,OPRD为转移地址的偏移量。

  • 该指令将程序执行的顺序转移到由(IP)+OPRD形成的新的程序执行的目标地址,从而实现程序的转移。

  • 转移的目标地址OPRD在指令中可以直接使用标号地址,但要求转移的目标地址的范围只能在JMP指令所处地址的-128~+127字节范围之内(补码表示),如超出该范围,汇编时出错 – 比如下面的代码中,越界了。

code segment
start:
	jmp short s 
	db 128 dup(0)	;跳转指令超出一个字节   error 
	s:mov ax,0ffffh
code ends
end start
  1. 近程转移(段内直接转移)
指令格式:JMP NEAR PTR OPRD
语法格式:JMP 地址标号 ;(IP)=(IP)+16位位移量

指令功能:

  • 与短程转移的功能和要求相同,不同之处是近程转移的OPRD为有符号的16位二进制数。
  • 指令将程序执行的顺序转移到由(IP)+OPRD形成的新的程序执行的目标地址,转移的目标地址的范围只能在
  • JMP指令所处地址的-32768~+32767字节范围之内,如超出该范围,汇编时出错。使用该指令时NEAR可省略。
  1. 段间直接转移(远程转移)
指令格式:JMP FAR PTR OPRD
语法格式:JMP 地址标号 ;(IP)= 新的偏移地址, ;(CS)= 新的代码段地址

指令功能:

  • 指令中用FAR PTR规定了该指令为段间的转移,OPRD为目的地址的标号,目的地址与JMP指令所在地址不在同一段内。
  • 执行该指令时要修改CS和IP的内容,将OPRD所在段的段地址送CS中,OPRD的段内偏移地址送IP中。
  1. 段内间接转移
指令格式:JMP WORD PTR OPRD
语法格式:JMP reg16/mem ;(IP)= 新的偏移地址

指令功能:

  • 与短程转移的功能和要求相同,不同之处是段内间接转移的OPRD 可以是除立即数外的任何寄存或存储器寻址方式
  • 转移的目标地址由OPRD的内容确定

远转移指明跳转到目标地址,包含了CS和IP,直接转移

近转移指明当前的IP偏移地址,而不是转移后的目的地址。

  1. 段间间接转移
指令格式:JMP DWORD PTR OPRD
语法格式:JMP mem32

指令功能:

  • 指令中用DWORD PTR规定了该指令为段间间接转移,OPRD只能是存储器寻址方式。
  • 执行该指令时将寻址到的内存单元的第一个字送入IP中,第二个字送入CS中。

jmp距离

  • 段间转移:同时修改CS和IP jmp 1000:0

  • 段内短转移:IP修改范围为-128~127 (八位 – 1个字节)

    jmp short 标号
    
  • 段内近转移:IP修改范围为-32768~32767 (十六位 – 2个字节 – 1个字)

    jmp near ptr 标号
    

jmp指令经常根据位移进行转移。

  • 常见指令的立即数在机器指令中有所体现

jmp short指令中,包含的是跳转到指令的相对位置,而不是转移的绝对位置。

jmp案例

依据位移进行转移

assume cs:codesg
codesg segment
start:
	mov ax,0
	jmp short s
	add ax,1
	s:inc ax
codesg ends
end start

程序执行后,ax 中的值为 1

因为执行 jmp short s 后,越过了 add ax,1

IP 指向了 标号 s 处的 inc ax

也就是说,程序只进行了一次 ax1 操作

此种转移方式并没有转移的目的地址,而是相对于当前 IP 的转移位移

另外,近转移ip修改范围: -32768~32767

转移的目的地址在指令中

语法: jmp far ptr 标号

这种实现的是 段间转移 ,又称为远转移

(CS)=标号所在段的段地址(IP)=标号在段中的偏移地址

far ptr 指明了指令用标号的段地址和偏移地址修改 CS 和 IP

比如:

assume cs:codesg
codesg segment
start:
	mov ax,0
	mov bx,0
	jmp far ptr s
	db 256 dup (0)
	s:add ax,1
	inc ax
codesg ends
end start

转移地址在寄存器中

指令格式: jmp 16 位 reg

功能: (IP)=(16 位 reg)

比如:

jmp ax

指令执行前: ax=1000H ,CS=2000H ,IP=0003H
指令执行后: ax=1000H ,CS=2000H ,IP=1000H
jmp ax ,相当于: mov IP,ax

转移地址在内存中

转移地址在内存中的jmp指令有两种格式

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

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

内存单元地址可用寻址方式的任一格式给出。

比如:

mov ax,0123H
mov ds:[0],ax	;ds:[0]中保存0123H
jmp word ptr ds:[0]		;跳转到0123H

执行后, (IP)=0123H


又比如:

mov ax,0123H
mov [bx],ax		;以bx寻址默认的段就是ds
jmp word ptr [bx]

执行后, (IP)=0123H

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

功能:从内存单元地址处开始存放着两个字

  • 高地址处的字是转移的目的段地址
  • 低地址处是转移的目的偏移地址
(CS) = (内存单元地址+2)
(IP) = (内存单元地址)

内存单元地址可用寻址方式的任一格式给出

比如:

mov ax,0123H
mov ds:[0],ax	;ip,偏移地址在低位
mov word ptr ds:[2],0	;0放入CS,段地址在高位
jmp dword ptr ds:[0]	

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


再比如:

mov ax,0123H
mov [bx],ax		;低地址 偏移地址:0123H
mov word ptr [bx+2],0 ;高地址 段地址:0
jmp dword ptr [bx]

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

注意

在源程序中,不允许使用jmp 2000:0100的转移指令实现段间转移

  • 这是在debug中使用的汇编指令,汇编编译器并不认识
  • 如果在源程序中使用,会报错

我们可以使用下面方式段间转移

jmp far ptr 标号
jmp dword ptr [bx]

其他的转移指令

jcxz指令

格式:

jcxz 标号

功能:

  • 如果(CS) = 0 ,则转移到标号处

    (ip) = (ip) + 8
    8位位移 = “标号” 处的地址 - jcxz指令后的第一个字节的地址
    和jmp短指令一样
    
  • 如果(CS) ≠ 0 ,则什么也不做(程序向下执行)

jcxz是条件转移指令

loop指令

前面有讲

格式:

loop 标号

功能:

  • (cx) = (cx) - 1
  • 如果(CS)≠ 0 ,则转移到标号处
  • 如果(CS)= 0 ,则什么也不做(程序向下执行)

上面根据位移进行“相对”转移的意义:

对IP的修改是根据转移目的地址和转移起始地址之间的唯一来进行

jmp short 标号 
jmp near ptr 标号
jcxz 标号 
loop 标号 

跳转指令总结

短转移 :-128~127 三类:标志转移、无/有符号数比较后转移

判断单个标志位状态

  • JZ/JE和JNZ/JNE:利用零标志ZF,判断结果是否为零(或相等)
  • JS和JNS:利用符号标志SF,判断结果是正是负
  • JO和JNO:溢出标志OF,判断结果是否产生溢出
  • JP/JPE和JNP/JPO:奇偶标志PF,判断结果中最低字节“1”的个数是偶是奇
  • JC/JB/JNAE和JNC/JNB/JAE:利用进位标志CF,判断结果是否进位或借位

END 链接