当然,如果汇编代码没办法运行也是枉然。让我们来用编译器生成我们所希望的真正的汇编代码。
# Here's the file we want to compile. $ cat return_two.c #include <stdio.h> int main() { return 2; } # Run the compiler with this file. $ ./babyc return_two.c Written out.s. # Check the output looks sensible. $ cat out.s .text .global _start _start: movl $2, %ebx movl $1, %eax int $0x80 |
非常棒!接着让我们来真正的运行一下编译之后代码来确保它能得到我们所想的结果。
# Assemble the file. We explicitly assemble as 32-bit # to avoid confusion on x86_64 machines. $ as out.s -o out.o --32 # Link the file, again specifying 32-bit. $ ld -m elf_i386 -s -o out out.o # Run it! $ ./out # What was the return code? $ echo $? 2 # Woohoo! |
我们踏出了第一步,接下去怎么做就全看你了。你可以按照那篇文章所指导的全部做一遍,然后制作一个更加复杂的编译器。你需要去写一个更加精巧的语法树来生成汇编代码。接下去的几步分别是:(1)允许返回任意的值(比如,return 3; 一些可执行代码);(2)添加对“非”的支持(比如,return ~1; 一些可执行代码)。每一个额外的特性都可以教你关于C语言的更多知识,编译器到底是怎么执行的,以及世界上其他编写编译器的人是如何想的。
这是构建 babyc 的方法。Babyc 现在已经拥有了if语句,循环,变量以及最基础的数据结构。欢迎你来check out它的代码,但是我希望看完我的文章你能够自己动手写一个。
不要害怕底层的一些事情。这是一个非常奇妙的世界。