跳到主要内容

C语言转换到汇编的过程

在C当中有一个main函数,main函数会完成一些工作,比如打印些数据,然后退出。这看起来很不错,但是,正如你们都在6.004中学到的,处理器其实并不能理解C语言,它们只能理解汇编语言的二进制码

在这张图片上,我在主板中圈出了RISC-V处理器。

注:原始资料引用了 lec05 图像资源,但压缩包中未包含该图片。

当我们说某个处理器是RISC-V处理器时,这意味着它可以理解RISC-V指令集。每一个处理器都有一个关联的isa(指令集架构),该指令集对于该处理器来说是有效的(可执行的)。每一个指令都有一个关联的二进制码或操作码。当处理器运行时遇上特定格式的二进制码,它就会知道执行什么操作。而我们这个主板上的处理器正好能够理解由C语言编译出的RISC-V汇编。

所以让C代码在你的处理器上运行的大致过程是写一段C代码把它编译成汇编,在这过程之中,会有一些链接(linking)操作以及其他类似操作,但是我们现在上的不是编译原理课(就不多说了)。然后,汇编将被翻译成二进制码,这就是目标文件,或者说是你看到的.o文件。如果你曾经在运行完“make qemu”之后留心过实验文件夹里有什么,你会看到一连串的.o文件,这些就是目标文件,处理器可以理解它们。还有你们已经看到的asm文件,你们可以回想一下,有一个usas.pl文件被编译成了一个usys.s文件,那个.s文件里面就是汇编语言,所以你们已经看到过RISC-V汇编代码了。如果你上过6.004课程,我相信你们已经看过大量的汇编代码。

总得来说,汇编的结构化程度看起来不如C语言。所以你们只能一行一行的阅读那些指令,你们会看到一些简单的指令,比如add,抑或是malt等等,诸如此类的非常多。在汇编中,没有直观的控制流,没有直观的循环语句,没有像C语言中一样直观的函数,你知道的,我们只能看到标签(labels)而不是真实的函数定义。汇编是相当底层的语言,有大量的其他语言可以被编译成汇编语言。这些过程对诸如C++之类的语言同样适用。任何编译型语言最终在底层都会变成汇编的形式,这就是让我们的计算机能够理解我们写的C代码的基本过程