3.汇编指令:【程序控制指令】转移指令、循环控制、 过程调用、中断控制

程序控制指令

程序控制类指令的本质是:控制程序的执行方向
决定程序执行方向的因素:CSIP
程序控制类指令的操作对象是:IPCS和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 有条件转移指令 …

  1. 根据单个条件标志的设置情况转移
    在这里插入图片描述
    这种转移指令常常用于适用于测试某一次运算的结果并根据其不同特征产生程序分支不同的处理的情况

  2. 比较两个无符号数,并根据比较的结果转移
    在这里插入图片描述

  3. 比较两个带符号数,并根据比较的结果转移
    在这里插入图片描述

  4. 常用
    在这里插入图片描述




二、循环转移指令

循环控制指令有几个要点:

  • 循环范围:以当前 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 的值去决定是否循环。

  1. LOOPZ(相等则循环):当 CX ≠ 0,且 ZF = 1时循环
  2. 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
中断服务程序的最后一条指令,负责恢复断点 、恢复标志寄存器内容

  • 9
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
要编写中断服务程序并使用`int`指令调用,您需要遵循以下步骤: 1. 编写中断服务程序:中断服务程序是一段代码,用于处理特定的中断请求。您需要使用汇编语言编写中断服务程序,并将其保存在一个文件中。这个程序应该是无限循环的,直到中断请求被处理完毕。 2. 将中断服务程序安装到中断向量表中:中断向量表是一个表格,用于存储中断服务程序的地址。每一个中断都有自己的向量号,您需要将中断服务程序的地址存储到相应的向量号位置上。 3. 在您的程序中使用`int`指令调用中断:在您的程序中,您可以使用`int`指令调用中断服务程序。`int`指令需要一个参数,即中断号。当您使用`int`指令时,处理器会跳转到相应的中断服务程序,并开始执行中断服务程序中的代码。 以下是一个简单的示例程序,演示了如何编写中断服务程序并使用`int`指令调用: ``` section .text global _start _start: ; 将中断服务程序安装到中断向量表中 mov eax, my_interrupt_handler mov [0x80 * 4], eax ; 使用int指令调用中断 mov eax, 0x80 int 0x80 ; 退出程序 mov eax, 1 xor ebx, ebx int 0x80 my_interrupt_handler: ; 在这里编写您的中断服务程序 ; ... ret ``` 在上面的示例程序中,我们将中断服务程序安装到向量号为0x80的位置上,并使用`int 0x80`指令调用中断服务程序。在中断服务程序中,您可以编写任何您需要的代码来处理中断请求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你说的白是什么白_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值