6.1 汇编代码生成简介
历经词法分析、语法分析、语义检查和中间代码生成阶段,我们终于来到了“目标代码生成阶段”,由于UCC编译器的目标代码即为32位x86汇编代码,因此我们就把本章称为“汇编代码生成”。UCC编译器中的大部分源代码都适用于Windows和Linux平台,但Windows平台上缺省的汇编器支持Intel风格的x86汇编代码,而Linux平台默认的汇编器则采用AT&T风格的x86汇编代码,两者在汇编语法上有一些差别,为节省篇幅,我们主要针对Linux平台的AT&T汇编进行讨论。到了这一章,UCC编译器面对的输入早已不再是C源代码,而主要是由各个基本块构成的链表,我们要把基本块中的中间代码翻译成x86汇编代码。我们在“第1.5节结合C语言来学汇编”中,已介绍过x86汇编代码的相关语法和语义,这里不再重复。
还是通过一个简单的例子来了解一下UCC编译器的汇编代码生成,如图6.1.1所示,第1至6行是一个简单的C程序,第11至58行是由UCC编译器产生的汇编代码。形如第13行C++风格的注释是我们人为加上去的,用于说明第14行的汇编代码“.data”是由Segment()函数产生。我们省略了main函数对应的汇编代码。
图6.1.1 汇编代码生成的例子
在C程序中出现的字符串可被视为全局的字符数组(当然对C程序员而言,该字符数组的名称不可见),通过第15行的EmitStrings()函数,UCC编译器可以为字符串产生形如第16行的字符数组,而通过第18行的EmitFloatConstants函数,则可以为形如“1.0”的浮点常数分配存储空间。UCC编译器会隐式地为字符串和浮点常数命名,例如第16行的“.str0”和第19行的“.flt0”,这些名字都以“.”开始。按C语言的语法,由C程序员命名的变量名或函数名不