我如何知道将映射哪些寄存器函数参数?

时间:2015-02-25 20:14:46

标签: c++ jit calling-convention

我为Brainfuck编写了一个JITting VM。它需要创建一个可写的+可执行的内存区域(它是char*,但不是用mallocnew创建的),它充满了机器操作码(在我的情况下为x64) ,然后在将char*转换为函数指针后调用。新创建的函数有参数。即,内存指针和其他一些内部事物。

它有效,但它假定某个寄存器映射。一段时间之前,这种映射已经发生了变化,因为我将调用的代码更改为char*,并且编译器认为它可以更好地与其他寄存器一起工作。所以我不得不改变代码生成方案。

我担心我会做一些会让编译器再次更改它的东西,或者更糟糕的是,使用堆栈,我不知道如何从(还)中提取参数。

所以我需要:

  • 一种告诉编译器放置参数的寄存器的方法(`register ... asm(“r0”),如here所述,不适用于参数)
  • 否则一种了解参数被映射到哪个寄存器的方法。这会使事情变得复杂,但它仍然可行。
  • 否则就知道参数是否以及以何种顺序在堆栈上传递

我正在使用gcc 4.8.2。

1 个答案:

答案 0 :(得分:1)

当你调用一个函数时,编译器通常不会选择放置调用参数的位置。这由ABI决定。如果您的宿主程序是用C ++编写的并且在Linux / x86-64机器上运行,它通常会发出符合SysV ABI中描述的调用约定的代码,该约定包含以下参数传递规则:

  

如果类是INTEGER,则序列%rdi的下一个可用寄存器,   使用%rsi,%rdx,%rcx,%r8和%r9。

值得注意的是,INTEGER类也包含指针参数。

这里的底线是你的jitted代码应该能够从上面列出的寄存器中挑选出它的参数。如果仍然无法正常工作,我怀疑您可能错误地编写了指令。尝试从GDB中查看反汇编。

(*)如果无法从翻译单元外部调用函数,则可以为编译器提供更大的灵活性。