2010-03-01 62 views
7

我目前正在通过Andrew Appel的Java编译器实现方式,并且我正在构建低级别中间表示法。为x86处理器生成汇编

最初,我决定瞄准JVM并忽略所有低级机器的东西,但为了学习我不了解的东西,我已经改变了心意。这改变了我的IR,因为以JVM为目标允许我(或多或少)在进行方法调用或构建对象时挥手。

Appel的书没有详细介绍任何特定的机器架构,所以我想知道我在哪里可以找到我需要知道的更远的地方。

我目前知道,我需要知道的事情是:

  • 的指令集来使用。我有两台笔记本电脑可以开发;都有Core 2 Duo处理器。我目前的理解是,x86处理器大多使用相同的指令集,但它们并不完全相同。

  • 操作系统是否影响编译的代码生成步骤,或者它是否完全依赖于处理器。例如,我知道生成代码在32位与64位平台上运行的不同之处。

  • 如何组织栈帧等。何时使用寄存器与将参数放入堆栈,调用者保存与被调用者保存,所有这些。我一直认为这将与指令集一起描述,但到目前为止我还没有在任何地方看到这个特定的信息。也许我在这里误解了一些东西?

以资源代替答案的链接非常受欢迎。

+0

投票结束太宽泛。 – 2015-10-01 12:20:18

回答

5

大多数x86指令集对于所有处理器都是通用的 - 这是一个合理安全的选择,您的处理器都具有相同的指令集,除了SIMD指令可能对您不太有用实现一个简单的编译器(这些指令通常用于制作多媒体应用程序等等)。指令集在Intel's manuals中列出 - 2A和2B中特别列出了指令及其行为,尽管其他卷值得关注。

当生成用户空间代码时,涉及到系统调用时操作系统的选择很重要。举例来说,如果你想有一个程序来输出不同的是在终端上64位Linux,你需要做一个系统调用:

  • 装载价值1到寄存器rax,表示这是一个write系统调用。
  • 装载价值1到寄存器rdi,表示标准输出应采用(1是标准输出文件描述符)
  • 加载的要打印到寄存器rsi
  • 装的是什么,你长什么的起始地址想要打印到寄存器rdx
  • 一旦寄存器(和存储器)已经建立,就执行syscall指令。

write的返回值存储在rax中。

不同的操作系统可能有不同的系统调用号为write,可能在参数传递(x86-64的Linux系统调用始终使用rdirsirdxr10r8不同的方式,并在r9系统调用号码为rax),并可能完全不同的系统调用。

普通功能的约定在Linux上调用类似 - 寄存器的顺序是rdirsirdxrcxr8r9(所以都是一样的,但是使用了rcx代替r10),进一步论证在堆栈上并返回值为rax。根据this page,寄存器rbp,rbxr12高达r15应保留跨功能调用。当然,你可以自由地构建自己的约定(除非进行系统调用),但是这使得从其他人生成或编写的代码中调用被调用更加困难。

+0

谢谢,迈克尔 - 这个答案也很有帮助。我希望我也能接受它;我自己的错误是要结合太多的问题。 +1,但。 – danben 2010-03-02 16:15:19

+0

其实,第二次阅读这篇文章,我认为这完全回答了我所有的问题。 – danben 2010-03-04 05:00:01

3

堆栈框架和 如何组织。何时使用寄存器与 将参数放在堆栈上, 调用者保存与被调用者保存,全部为 。我一直以为这将 与 指令集一起描述,但到目前为止我没有 在任何地方看到这个特定的信息。 也许我在误解 这里?

一般来说,这些问题没有正确的答案。你可以使用你想要的任何调用约定......除非你想与其他人的代码进行互操作。为了实现互操作性,编译器在应用程序二进制接口上进行标准化。我的理解是,Itanium C++ ABI近年来已成为流行的标准。尝试从那里开始。

+0

谢谢,内森。我不太了解Itanium C++ ABI的目的,因为它与我的目的有关(例如,C++在为另一种语言开发编译器时扮演了什么角色?);然而,这个链接最终导致了我正在寻找的各种x86调用约定(cdecl等)。 – danben 2010-03-02 16:14:14

1

我无法回答你们所有的问题;但

  • 基本x86指令集是整个x86系列处理器 的 兼容。你不打算 实施任何具体的扩展, 你呢?
  • 我不认为你的OS 或结构问题多的代码 代
  • 默认答案相关 任何编译器是 Dragon book。你有没有看过 呢?