在gcc内联汇编中引用寄存器的高半部分的任何约束?

时间:2011-04-05 09:52:15

标签: gcc x86 inline-assembly

在我的C代码中,有一些内联汇编调用PCI BIOS服务。现在问题是其中一个结果在%ah寄存器中返回,但我找不到一个constrant来引用该寄存器。

我想要写的如下:

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

并且变量status包含%ah寄存器的值。

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

有什么建议吗?

1 个答案:

答案 0 :(得分:0)

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

你的方法会奏效;另一个选择是将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测试代码生成;其他版本的结果可能会有所不同。)