汇编语言流程转移与子程序篇--05

2022-07-12 15:44:23 浏览数 (1)

汇编语言流程转移与子程序篇--05

  • “转移”综述
  • 操作符offset
    • 用操作符offset取得标号的偏移地址
    • 练习
  • jmp指令
    • jmp指令——无条件转移
    • jmp指令:依据位移进行转移
    • 两种段内转移
    • 远转移:jmp far ptr 标号
    • 转移地址在寄存器中的jmp指令
    • 转移地址在内存中的jmp指令
    • jmp指令小结
  • 其他转移指令
    • jcxz指令
    • loop指令
    • 根据位移进行“相对”转移的意义
  • call指令和ret指令
    • 模块化程序设计
    • call 指令
    • 指令“call far ptr 标号”实现的是段间转移
    • 转移地址在寄存器中的call指令
    • 转移地址在内存中的call指令
    • 返回指令:ret 和 retf
  • call 和 ret 的配合使用
    • 具有子程序的源程序的框架
    • call 和 ret 的配合使用
    • 例:为call和ret指令设置栈
  • 乘法:mul 指令
    • 回顾:除法div 指令
    • 用 mul 指令做乘法
    • 应用实例
  • 汇编语言的模块化程序设计
    • 模块化程序设计
    • 参数和结果传递的问题
    • 用寄存器来存储参数和结果是最常使用的方法
    • 用内存单元批量传递数据
    • 用栈传递参数
      • 程序的执行过程中栈的变化
    • 小结:参数和结果传递的问题
  • 寄存器冲突问题
    • 引子
    • 代码:编程将data段中的字符串转化为大写
    • 寄存器冲突问题的解决
    • 寄存器冲突问题的解决示例
  • 标志寄存器
    • 认识标志寄存器的特殊之处
      • ZF-零标志(Zero Flag)
      • PF-奇偶标志(Parity Flag)
      • SF-符号标志(Sign Flag)
      • CF-进位标志(Carry Flag)
      • OF-溢出标志(Overflow Flag)
  • 带进(借)位的加减法
    • adc-带进位加法指令
    • adc指令应用:大数相加
    • 128位数据的相加
    • sbb指令
  • cmp与条件转移指令
    • cmp指令
    • 无符号数比较与标志位取值
    • 有符号数比较与标志位取值
    • 条件转移指令
    • 条件转移指令的使用
  • 条件转移指令应用
    • 应用示例
  • DF标志和串传送指令
    • 问题的提出
    • DF标志和串传送指令
    • rep指令
    • 应用实例

本系列文章参考汇编语言第四版和汇编语言程序设计 贺利坚主讲整理而成


“转移”综述


操作符offset

用操作符offset取得标号的偏移地址


练习


jmp指令

jmp指令——无条件转移

jmp指令的功能 : 无条件转移,可以只修改IP,也可以同时修改CS和IP

jmp指令要给出两种信息:

  • 转移的目的地址
  • 转移的距离

  • 段间转移(远转移): jmp 2000:1000
  • 段内短转移: jmp short 标号 ; IP的修改范围为 -128~127,8位的位移
  • 段内近转移: jmp near ptr 标号 ; IP的修改范围为 -32768~32767,16位的位移

jmp指令:依据位移进行转移

代码语言:javascript复制
076A:0003 EB03 JMP 0008
076A:0005 050100 ADD AX,0001
076A:0008 40 INC AX
  • 当JMP指令被读入指令缓冲器后,IP=IP 所读取的指令长度=0005
  • CPU执行指令缓冲器中的指令EB03
  • IP=IP 3=0005 0003=0008

JMP short s : 对应的机器指令中,包含的是当前指令下一条指令开始位置处,到段内目标地址的位移


两种段内转移


远转移:jmp far ptr 标号

远转移(跨段转移)中,转移机器指令中包含的是目标地址,而不是相对位移


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


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


jmp指令小结


其他转移指令

jcxz指令


loop指令


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


call指令和ret指令

模块化程序设计


call 指令

将当前IP或CS和IP压栈,是为了子程序调用结束后,程序能够回到原来的位置,继续往下面执行


指令“call far ptr 标号”实现的是段间转移


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


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


返回指令:ret 和 retf

设计用来回到子程序调用结束后,源程序继续运行的地址处


call 和 ret 的配合使用

具有子程序的源程序的框架


call 和 ret 的配合使用

注意观察在调用call指令和ret指令时,sp栈顶寄存器值的变化

call需要使用栈,但是这里程序没有分配栈空间,是默认给出的栈空间,因此这是非常危险的,鬼知道默认的空间,是不是在别的啥子地方被占用了


例:为call和ret指令设置栈


乘法:mul 指令

回顾:除法div 指令


用 mul 指令做乘法


应用实例


汇编语言的模块化程序设计

模块化程序设计


参数和结果传递的问题


用寄存器来存储参数和结果是最常使用的方法


用内存单元批量传递数据


用栈传递参数

保存BP寄存器旧值的原因,在于子程序中需要使用到BP寄存器,而BP寄存器可能在主程序或者其他程序中被使用中,因此当前子程序用完BP寄存器后,需要恢复其旧值才可以。

ret 4是先恢复IP寄存器原先值,然后再讲SP栈顶地址寄存器的偏移值 4,这里是跳过a和b两个数据,因为这两个值没用了,不需要继续占据着栈空间


程序的执行过程中栈的变化


小结:参数和结果传递的问题

问题:根据提供的N,计算N的3次方。

考虑

  • (1)我们将参数N存储在什么地方?
  • (2)计算得到的数值,存储在什么地方?

方案:

  • 用寄存器传递参数
  • 用内存单元进行参数传递
  • 用栈传递参数

寄存器冲突问题

引子

之前我们每次循环时,都是提前将要循环的次数保存在了cx寄存器中,但是有没有办法不提前写好循环次数,而在合适的时机结束循环呢?

  • 在处理字符串问题时,可以模仿c语言的结束符号

代码:编程将data段中的字符串转化为大写

cx寄存器使用的冲突,会导致程序运行的奔溃,这是个大问题,怎么解决呢?


寄存器冲突问题的解决


寄存器冲突问题的解决示例


标志寄存器


认识标志寄存器的特殊之处


ZF-零标志(Zero Flag)


PF-奇偶标志(Parity Flag)


SF-符号标志(Sign Flag)


CF-进位标志(Carry Flag)


OF-溢出标志(Overflow Flag)


带进(借)位的加减法

adc-带进位加法指令

对于最后一种因为减法产生借位而导致CF=1的情况,显然不是我们期望的样子,因此是存在问题的,但是这种问题的解决需要程序员自己去控制


adc指令应用:大数相加


128位数据的相加

  • sub ax,ax不可以替换为mov ax,0 ,因为sub ax,ax算出来ax=0后,因为没有产生借位,因此CF=0,确保能够清空CF之前的状态,确保不会影响下面的adc操作
  • inc di不会影响进位标志位CF,但是add di 2会影响CF标记位,如果发生溢出了,CF会被设置为1

sbb指令

  • 低十六位相减,如果产生了借位,那么高16位就需要处理低十六位产生的借位

cmp与条件转移指令

cmp指令


无符号数比较与标志位取值


有符号数比较与标志位取值


条件转移指令


条件转移指令的使用


条件转移指令应用


应用示例




DF标志和串传送指令

问题的提出


DF标志和串传送指令


rep指令


应用实例

0 人点赞