文章目录
程序控制指令
程序控制类指令的本质是:控制程序的执行方向
决定程序执行方向的因素:CS
,IP
程序控制类指令的操作对象是:IP
或 CS和IP
控制程序执行方向的方法:
程序控制指令包含4类:转移指令
、循环控制
、 过程调用
、中断控制
一、 转移指令
转移是通过修改下一条要执行指令的偏移地址
或段地址和偏移地址
实现程序的转移
分为:
1.1 无条件转移指令 JMP
分为直接转移 和 间接转移
分为段内(16位) 和 段间(32位)
直接和间距的区别就是,前者是直接给地址,后者通过寄存器或者其他
段间和段内的区别就是,前者32位(CS:IP 故32位),后者是16位(就ip,所以16位)
1.1.1 段内直接
JMP Label
Label
: 指向下一条代码的地址
1.1.2 段内间接
如果我们是通过指令里面的寄存器 或者 存储器操作数
给出的目标地址,就称为间接转移。例如:
MOV BX, 1200H
JMP BX //运行完了之后 IP = 1200H,这里 BX 是寄存器操作数
另外一种表现形式:
MOV BX, 1200 //注意:这里不是 H
JMP WORD PTR [BX] //这样一来,我们把数据段里面 标号为 1200和 1201 的两个单元分别赋给 IP的低位和高位
段内间接例子
还是以上面的为例,如果我们的 Label 符号是 32 位的地址,那么就表示 段间转移。
同样,段间转移也分为了 段间直接转移
和段间间接转移
。
段间直接转移
就是我们在指令里面直接给出 32 位目标地址(CS:IP)
段间间接转移
就是需要通过 32 位的存储器操作数(注意不能是寄存器了)给出目标地址。
1.1.3 段间直接
对于段间直接转移,指令格式是:JMP FAR Label(FAR 代表远地址)
1.1.4 段间间接
那么对于段间间接转移,我们可以用下面的表述:
JMP DWORD PTR[BX] //[BX]指向的是存储器操作数
段间间接例题:
1.2 有条件转移指令 …
-
根据
单个条件标志的设置情况
转移
这种转移指令常常用于适用于测试某一次运算的结果并根据其不同特征产生程序分支不同的处理的情况 -
比较两个无符号数
,并根据比较的结果转移
-
比较两个带符号数
,并根据比较的结果转移
-
常用
二、循环转移指令
循环控制指令有几个要点:
- 循环范围:以当前 IP 为中心的 -128~ +127的范围内循环
- 循环次数:循环的次数必须要由 CX 寄存器指定。
- 循环指令也分为
无条件循环 LOOP
和条件循环指令 LOOPZ/ LOOPNZ
2.1 无条件循环指令 LOOP
格式:LOOP Label
等价于:(这个有点不确定)
DEC CX
JNZ 符合地址
循环的条件是:当 CX ≠ 0
时。
2.2 条件循环指令 LOOPZ/ LOOPNZ
功能:先使得 CX -1,再根据 CX 的值以及 ZF 的值去决定是否循环。
- LOOPZ(相等则循环):当
CX ≠ 0
,且ZF = 1
时循环 - LOOPNZ(不相等则循环):当
CX ≠ 0
,且ZF = 0
时循环
因此,条件循环指令前面需要跟能够改变 ZF 状态的指令,用以控制循环
三、过程调用指令
过程调用,就是类似于我们在 C++ 里面的主程序中调用子函数一样。
那么话说回来,我们在刚刚所讨论的转移类指令
,是程序运行到某个地方之后,就跳转到另外一段代码,不会再回到原处了。
但是对于过程调用指令
,我们跳转到子程序运行完了之后,是需要回到原来的地方继续执行主程序的。
用下面的图说明一下
注意:我们执行完子程序返回的位置是原来跳转位置的后一条指令!
因此,既然需要返回原来的位置,也就不能忘了初心。
过程调用指令需要保护返回地址(也就是 段基地址 和 偏移地址)。即我们需要把 CS 和 IP 里面的内容压栈。
3.1 基本格式
调用指令:
CALL <子过程的入口地址>
返回指令:RET
分为直接转移 和 间接转移
分为段内(16位) 和 段间(32位)
3.2 段内 直接/间接 调用例子
3.3 段间 直接/间接 调用例子
3.4 CALL指令执行对堆栈的影响
四、中断控制
响应中断,即针对某个随机或异常事件执行一段处理程序,称为中断服务程序,本质上是一种特殊的过程调用,且全部是远过程调用。
指令格式:INT n
n=0 ~ 255
执行过程:
中断指令的执行过程示例
中断指令例子
中断返回指令
格式:IRET
中断服务程序的最后一条指令,负责恢复断点 、恢复标志寄存器内容