在 gcc 内联汇编中引用寄存器的高半部分有任何限制吗?

发布于 2024-10-31 02:13:17 字数 361 浏览 0 评论 0原文

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

我想要的是像下面这样写:

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

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

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

有什么建议吗?

In my C code there are some inlined assembly calling PCI BIOS service. Now the problem is that one of the results is returned in the %ah register, but I can't find a constrant to refer to that register.

What I want is to write like following:

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

and the variable status contains the value of %ah register.

If I use "=a"(status) and add a mov %%ah, %%al instruction it will work. But it seems ugly.

Any suggestions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

樱花落人离去 2024-11-07 02:13:17

我认为没有办法在约束中指定 %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 进行测试;其他版本的结果可能会有所不同。)

I don't think there is a way to specify %ah in a constraint - the GCC x86 backend knows that sub-registers contain particular parts of values, but doesn't really treat them as independent entities.

Your approach will work; another option is to shift status down outside the inline assembler. e.g. this:

unsigned int foo(void)
{
  unsigned int status;

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

...implements the (status >> 8) & 0xff as a single movzbl %ah, %eax instruction.

A third option is to use a small structure:

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

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

I'm not sure whether this is nicer or not - it seems a little more self-documenting, but the use of a small structure with a register constraint looks less obviously correct. However, it generates the same code as foo() above.

(Disclaimer: code generation tested with gcc 4.3.2 only; results may well differ on other versions.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文