2011-07-13 80 views
21

这是一个奇怪的请求,但我有一种感觉,这可能是可能的。我想要的是在我的代码的区域中插入一些编译指示或指令(用C编写),以便GCC的寄存器分配器而不是使用它们。GCC:禁止使用一些寄存器

我知道我可以做这样的事情,这威力抛开这个寄存器此变量

register int var1 asm ("EBX") = 1984; 
register int var2 asm ("r9") = 101; 

的问题是,我插入新的指令(硬件仿真器)直接和海湾合作委员会和气体仍不承认这些。我的新指令可以使用现有的通用寄存器,并且我想确保我保留了其中的一些(即r12-> r15)。

现在,我在模拟环境中工作,我想快速做我的实验。将来我会追加GAS并将内在函数添加到GCC中,但现在我正在寻找一个快速解决方案。

谢谢!

+1

您是否需要在任何时候保留它们,或者仅仅是在某些特定的内联asm块的过程中保留它们? – bdonlan

+0

是的,我应该说明这一点。我只需要在小功能的环境中保留它们。我担心,通过在全球范围内保留它们,可能会对性能产生减少的影响。 – hayesti

回答

12

在编写GCC内联汇编程序时,可以指定一个“clobber list” - 一个可能被内联汇编程序代码覆盖的寄存器列表。然后,GCC将在内联部分的过程中做任何需要的操作来保存和恢复这些寄存器中的数据(或者首先避免它们的使用)。您还可以将输入或输出寄存器绑定到C变量。

例如:

inline unsigned long addone(unsigned long v) 
{ 
    unsigned long rv; 
    asm("mov $1, %%eax;" 
     "mov %0, %%ebx;" 
     "add %%eax, %%ebx" 
     : /* outputs */ "b" (rv) 
     : /* inputs */ "g" (v) /* select unused general purpose reg into %0 */ 
     : /* clobbers */ "eax" 
     ); 
} 

有关详细信息,请参阅GCC-Inline-Asm-HOWTO

+0

会给你+1,除了你的例子中的语法是错误的 - 你需要在clobber列表中实际的寄存器名称而不是约束代码,所以''eax“'而不是''a”' –

+0

@Chris,哎呀 - 修正:) – bdonlan

+0

谢谢,这也是非常有用的。 :-) – hayesti

5

如果您使用的是global explicit register variables,这些将在整个编译单元中保留,编译器不会将其用于其他任何内容(它可能仍然会被系统的库使用,因此请选择那些将由其恢复的内容) 。本地寄存器变量不能保证您的值始终位于寄存器中,而只能通过代码或asm操作数引用。

+1

谢谢,我没有意识到全局寄存器变量保证了这一点。 – hayesti

+1

@Bob:你应该也可以看到这个页面,它包含一些警告(例如信号),它还提到'-ffixed-reg',如果重新编译库不会混淆你的寄存器,你可以使用它增加一个全局寄存器变量。 http://gcc.gnu.org/onlinedocs/gcc-4.6.1/gcc/Global-Reg-Vars.html#Global-Reg-Vars – Hasturkun

+0

我认为这个-ffixed-reg看起来很完美!我假设,因为它是一个代码生成标志,如果我内联程序集明确使用这些禁止的寄存器,它会好吗? – hayesti

5

如果你为你的新指令写了一个内联asm块,有一些命令告诉GCC该块使用了哪些寄存器以及它们是如何使用的。然后GCC将避免使用这些寄存器或至少保存并重新加载其内容。

+0

谢谢你的回答。如果你有一个链接到这个功能的文档,这将是太棒了。 – hayesti

+1

@Bob:参见http://gcc.gnu。org/onlinedocs/gcc-4.6.1/gcc/Extended-Asm.html#Extended-Asm和http://gcc.gnu.org/onlinedocs/gcc-4.6.1/gcc/Constraints.html#Constraints – Hasturkun

+0

很棒,谢谢! – hayesti