dan*_*ben 7 compiler-construction x86 assembly code-generation
我目前正在通过Andrew Appel的Java中的现代编译器实现工作,我正处于建立低级中间表示的地步.
最初,我决定瞄准JVM并忽略所有低级机器的东西,但为了学习我不太了解的事情,我已经改变了主意.这会改变我的IR,因为以JVM为目标允许我(或多或少)挥动我的手来进行方法调用或构建对象.
Appel书没有详细介绍任何特定的机器架构,所以我想知道在哪里可以找到我需要知道的更远的东西.
我现在知道的事情我需要知道的是:
使用哪个指令集.我有两台可以开发的笔记本电脑; 两者都有Core 2 Duo处理器.我目前的理解是x86处理器大多使用相同的指令集,但它们并非完全相同.
操作系统是否影响编译的代码生成步骤,或者它是否完全依赖于处理器.例如,我知道生成在32位与64位平台上运行的代码有所不同.
如何组织堆栈帧等.何时使用寄存器与在堆栈上放置参数,调用者保存与被调用者保存,所有这些.我曾经想过这将与指令集一起描述,但到目前为止我还没有在任何地方看到这个特定的信息.也许我在这里误解了什么?
完全欢迎链接到资源以代替答案.
大多数x86指令集对所有处理器都是通用的 - 这是一个相当安全的选择,你的处理器都有相同的指令集,除了可能的SIMD指令,在实现一个简单的编译器时可能对你没有用处(这些指令通常用于使多媒体应用程序等更快).英特尔手册中列出了该指令集- 特别是2A和2B有完整的指令列表及其行为,但其他卷值得一看.
在生成用户空间代码时,操作系统的选择在系统调用方面很重要.例如,如果您希望程序在64位Linux上向终端输出内容,则需要通过以下方式进行系统调用:
rax以指示这是write系统调用.rdi以指示应该使用stdout(1是stdout的文件描述符)rsirdxsyscall一旦设置了寄存器(和存储器),就执行该指令.返回值write存储在rax.
不同的操作系统可能有不同的系统调用号write,可能会传递参数的不同方式(x86-64的Linux系统调用经常使用rdi,rsi,rdx,r10,r8,并r9在为了参数,与系统中的呼叫号码rax) ,可能会有不同的系统调用.
对于普通函数调用在Linux上的惯例是类似的-寄存器的顺序是rdi,rsi,rdx,rcx,r8,和r9(所以都是一样的,但是使用了rcx代替r10),用堆和一个返回值上进一步论证rax.根据这个页面,寄存器rbp,rbx和r12最多r15应该在函数调用之间保留.当然,您可以自由地构建自己的约定(除非进行系统调用),但这使得调用从其他人生成或编写的代码调用变得更加困难.