【汇编语言与计算机系统结构笔记15】子程序设计:调用与返回,保护与恢复寄存器,子程序的参数传递,堆栈平衡,结构伪操作 STRUC

本次笔记内容:
20.子程序设计-1-1
21.子程序设计-1-2
22.子程序设计-1-3

注:我找到了对应内容的课件,请见我于{GitHub的CS笔记仓库](https://github.com/PiperLiu/CS-courses-notes)。因此,为了节省时间,我只记录老师上课强调的内容与对应ppt页码。

本节课对应幻灯片:汇编语言程序设计-循环与分支,第1页起。

上节课第 5 章刚刚结束,进入第 6 章“子程序结构”。视频一共三节课,第一节30分钟。其中,第一节老师讲了讲高级的汇编语言规则(高版本汇编器识别),包括标号的作用域、循环伪指令等等。

【汇编语言与计算机系统结构笔记15】子程序设计:调用与返回,保护与恢复寄存器,子程序的参数传递,堆栈平衡,结构伪操作 STRUC
如图,并没有 ppt ,课件资源里也没有,因此本节的前 1/3 只能选择性跳过。

前1/3内容如标号决定作用域:过程、全局还是其他等等。

P2 主要内容

  • 过程定义伪操作
  • 子程序的调用与返回
  • 保存与恢复寄存器
  • 子程序的参数传送(汇编语言来讲,参数传递我们亲自来做)
  • 子程序的嵌套与递归(比高级语言麻烦一些)

P3- 过程定义伪操作

【汇编语言与计算机系统结构笔记15】子程序设计:调用与返回,保护与恢复寄存器,子程序的参数传递,堆栈平衡,结构伪操作 STRUC
(1)NEAR属性:调用程序和子程序在同一代码段中(段内调用)

(2)FAR属性:调用程序和子程序不在同一代码段中(段间调用)
【汇编语言与计算机系统结构笔记15】子程序设计:调用与返回,保护与恢复寄存器,子程序的参数传递,堆栈平衡,结构伪操作 STRUC
如上,我们定义的过程名字是我们自己写的。习惯上,将主程序命名为 main 。注意段内调用与段间调用的区别。段间调用,定义了两个 segment 。

P5 子程序的调用与返回

【汇编语言与计算机系统结构笔记15】子程序设计:调用与返回,保护与恢复寄存器,子程序的参数传递,堆栈平衡,结构伪操作 STRUC
段间调用,因为短地址改变了,一定是先压入段地址,之后再压IP。

ret 后可以是立即数:

  • 对于实模式,必须是偶数;
  • 对于保护模式,4、8、12这种。
  • 后面会讨论具体什么意思。

P6 保存与恢复寄存器

【汇编语言与计算机系统结构笔记15】子程序设计:调用与返回,保护与恢复寄存器,子程序的参数传递,堆栈平衡,结构伪操作 STRUC
一般,要把用到的寄存器保存起来。push和pop都成对的。

P7 子程序的参数传递

  • (1) 通过寄存器传送参数
  • (2) 通过存储器传送参数
  • (3) 通过地址表传送参数地址
  • (4) 通过堆栈传送参数或参数地址
  • (5) 多个模块之间的参数传送

P8- 例:十进制到十六进制的转换(通过寄存器传送参数)

【汇编语言与计算机系统结构笔记15】子程序设计:调用与返回,保护与恢复寄存器,子程序的参数传递,堆栈平衡,结构伪操作 STRUC
【汇编语言与计算机系统结构笔记15】子程序设计:调用与返回,保护与恢复寄存器,子程序的参数传递,堆栈平衡,结构伪操作 STRUC

P10- 例:十六进制到十进制的转换(通过寄存器传送参数)

【汇编语言与计算机系统结构笔记15】子程序设计:调用与返回,保护与恢复寄存器,子程序的参数传递,堆栈平衡,结构伪操作 STRUC
【汇编语言与计算机系统结构笔记15】子程序设计:调用与返回,保护与恢复寄存器,子程序的参数传递,堆栈平衡,结构伪操作 STRUC

P12- 例:累加数组中的元素(通过存储器传送参数)

【汇编语言与计算机系统结构笔记15】子程序设计:调用与返回,保护与恢复寄存器,子程序的参数传递,堆栈平衡,结构伪操作 STRUC
【汇编语言与计算机系统结构笔记15】子程序设计:调用与返回,保护与恢复寄存器,子程序的参数传递,堆栈平衡,结构伪操作 STRUC
注意,基本不用这种方法,因为不可复用。

因此引出下面的,地址表传参的例子。

P14- 例:累加数组中的元素(通过地址表传送参数地址)

【汇编语言与计算机系统结构笔记15】子程序设计:调用与返回,保护与恢复寄存器,子程序的参数传递,堆栈平衡,结构伪操作 STRUC
如上,应该把地址表的地址给bx,再调用某个数时,就不用“直呼其名”了。
【汇编语言与计算机系统结构笔记15】子程序设计:调用与返回,保护与恢复寄存器,子程序的参数传递,堆栈平衡,结构伪操作 STRUC
如上是子程序与内存中的样子。

P16 通过堆栈传送参数或参数地址

【汇编语言与计算机系统结构笔记15】子程序设计:调用与返回,保护与恢复寄存器,子程序的参数传递,堆栈平衡,结构伪操作 STRUC
实际上,用的多的,也是用堆栈传参。堆栈其实也是内存的一块区域。高级语言用的也是堆栈传参。

下面,举个例子看看堆栈段传参。

P17- 例:累加数组中的元素(通过堆栈传送参数地址)

【汇编语言与计算机系统结构笔记15】子程序设计:调用与返回,保护与恢复寄存器,子程序的参数传递,堆栈平衡,结构伪操作 STRUC
如上,在汇编中,可以先用,后定义。

在堆栈段中,要了 200 个字节。st初值00c8
【汇编语言与计算机系统结构笔记15】子程序设计:调用与返回,保护与恢复寄存器,子程序的参数传递,堆栈平衡,结构伪操作 STRUC
一般来说,一段程序里,有几个 push,就应该有几个 pop 。红字上面的两个 push ,对应 push ds 与 push 0,是与 ret 对应的(一般来说,ret相当于两个 pop)。

但是红字额外多了3个push?看起来,没弹出去?实际上,可以在proadd这个过程中弹出去。
【汇编语言与计算机系统结构笔记15】子程序设计:调用与返回,保护与恢复寄存器,子程序的参数传递,堆栈平衡,结构伪操作 STRUC
如上,出现了一个代立即数的返回:

  • 调用 ret 前,指向 ip 的位置;
  • ret 是两个 pop,pop掉了 ip 与 cs ;
  • ret 6 表示,自动跳过 6 个字节(0000, 0014, 0016)。

如果就写了 ret ,那这 3 个字,则交给主程序处理。

这个叫堆栈平衡,不同模式下,堆栈平衡由不同程序处理。

此外,老师又举了不少例子;没有ppt,有些无奈。

P20- 结构伪操作 STRUC

定义一种可包含不同类型数据的结构模式。

【汇编语言与计算机系统结构笔记15】子程序设计:调用与返回,保护与恢复寄存器,子程序的参数传递,堆栈平衡,结构伪操作 STRUC
如上,并没有用子程序定义变量。

接下来举了一个例子,累加数组中的元素(通过堆栈传送参数地址)。

【汇编语言与计算机系统结构笔记15】子程序设计:调用与返回,保护与恢复寄存器,子程序的参数传递,堆栈平衡,结构伪操作 STRUC
【汇编语言与计算机系统结构笔记15】子程序设计:调用与返回,保护与恢复寄存器,子程序的参数传递,堆栈平衡,结构伪操作 STRUC
如上,可以不用[bp+0ah]这种形式,可以使用[bp].par3_addr这种形式。

这适于下节课的递归中的“帧”内容,其调用时递归的,有规律的。