生成汇编代码
复习
- 指令选择:决定用哪些机器指令
- 寄存器着色与溢出:决定值放在哪里
- 栈帧:函数调用时的栈布局
TL;DR
- 生成汇编,是把前面所有决定落成具体的文本
- 此时指令、寄存器、栈位置都已确定
- 汇编之后还要经汇编器变成机器码
- 后端到此基本完成
正文
这是后端代码生成的最后一步。前面的决定——用哪些指令、每个值放哪个寄存器、栈帧怎么摆——都做好了,现在要做的,是把它们写成具体的汇编代码。
把决定“抄”下来
到了这一步,其实“思考”已经基本结束,剩下的更像“誊写”:
- 指令选择已经定了 ××× 用哪条指令
- 寄存器分配已经定了每个变量待在哪个寄存器
- 栈帧布局已经定了局部变量和溢出值在栈上的偏移
生成汇编,就是把这些决定,按机器的语法一字一句写出来。
一个例子
比如这样一段简单代码 a = b + c,经过前面的处理,可能被生成成:
load r1, [b] ; 把 b 从内存读进寄存器 r1
load r2, [c] ; 把 c 读进 r2
add r3, r1, r2 ; r3 = r1 + r2
store [a], r3 ; 把结果写回 a
原本一句 a = b + c,被拆成了“取数、取数、相加、存回”几条指令。这和我们前面讲三地址码时的“拆解”,思路一脉相承——只不过这次拆的是真正的机器指令。
如果 b、c 已经在寄存器里,或者机器支持“基址 + 偏移”的寻址模式,生成的指令还会更少。具体长什么样,取决于前面指令选择和寄存器的决定。
之后还有什么
汇编代码并不是终点。它还要交给汇编器,翻译成二进制的机器码,生成目标文件;再经过链接,才能变成可执行文件。
这两步——汇编和链接——我们在讲程序与编程基础时提过,当时当作黑箱。现在我们已经走到了它们的门口。下一组,就正式打开链接这个黑箱。
思考题 1
到“生成汇编”这一步,哪些决定已经确定了?
思考题 2
生成的汇编,之后还要经过什么,才能变成可执行文件?
小结
知识点
- 生成汇编把指令、寄存器、栈布局落成文本
- 简单语句会被展开成多条机器指令
- 汇编再经汇编器变为机器码,生成目标文件
- 之后还需链接才能得到可执行文件
参考资料
- Wikipedia(zh):汇编语言:与机器指令对应的低级语言
- Wikipedia(zh):代码生成:后端生成目标代码的过程
思考题答案(仅供参考)
思考题 1
指令选择(用哪些机器指令)、寄存器分配(每个值放在哪个寄存器或内存)、以及栈帧布局(局部变量与溢出值在栈上的位置)都已经确定,生成汇编只是把这些决定写成具体的汇编文本。
思考题 2
汇编代码要先经汇编器翻译成二进制机器码,形成目标文件;多个目标文件还要再经过链接,解决符号与地址的引用,才能最终得到可执行文件。
协议
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
封面图
设计师 | 南国微雪