2011-04-05 58 views
1

在我的C代码中有一些内联程序集调用PCI BIOS服务。现在问题是其中一个结果返回%ah寄存器,但我找不到引用该寄存器的常量。任何约束来引用gcc内联汇编中的寄存器的高一半?

我想要的是编写类似以下内容:

asm("lcall *%[call_addr]" : "something here"(status) :); 

和可变status包含%ah寄存器的值。

如果我使用"=a"(status)并添加mov %%ah, %%al指令它会工作。但它看起来很丑。

有什么建议吗?

回答

0

我不认为有一种方法可以在约束中指定%ah - GCC x86后端知道子寄存器包含值的特定部分,但并不真正将它们视为独立实体。

您的方法可行;另一种选择是将status向内移入汇编程序外。例如这样的:

unsigned int foo(void) 
{ 
    unsigned int status; 

    asm("movb $0x12, %%ah; movb $0x34, %%al" : "=a"(status) :); 
    return (status >> 8) & 0xff; 
} 

...实现(status >> 8) & 0xff作为一个单一的movzbl %ah, %eax指令。

第三种选择是使用一个小的结构:

unsigned int bar(void) 
{ 
    struct { uint8_t al; uint8_t ah; } status; 

    asm("movb $0x12, %%ah; movb $0x34, %%al" : "=a"(status) :); 
    return status.ah; 
} 

我不知道这是否是漂亮与否 - 它似乎多了几分自我记录,而是使用一个小的结构与寄存器约束看起来不太明显正确。但是,它会生成与上面的foo()相同的代码。

(免责声明:代码生成仅用gcc 4.3.2测试;结果可能在其他版本上有所不同)。

+0

感谢您的帮助。在这篇文章之前,我已经尝试了两种解决方案。对于你的第三个选择,我使用了一个联盟,我认为它会有更好的外观。这些解决方法的一个常见问题是它们需要额外的代码,使封装函数相当长。我认为在找到更好的方法之前,必须保持现有的方法。 – hpsMouse 2011-04-08 11:00:28