[英]How do I get GCC to put a char in ah/bh/ch/dh?
假設我有一些內聯程序集需要ah
、 bh
、 ch
或dh
中的特定char
值。 我怎么能告訴 GCC 把它放在那里? 我沒有看到相關的約束,但是 GCC 手冊說“如果您必須使用特定的寄存器,但您的機器約束不能為 select 您想要的特定寄存器提供足夠的控制,本地寄存器變量可能會提供解決方案“,所以我嘗試了:
void f(char x) {
register char y __asm__("ah") = x;
__asm__ __volatile__(
"# my value ended up in %0" :: "a"(y)
);
}
但它沒有用。 它把它放在al
中:
movb 4(%esp), %al
# my value ended up in %al
x86 特定的Q
約束看起來也接近我想要的,所以我嘗試用它代替a
,但結果相同。 我還嘗試了更通用的r
。
有趣的是,當我使用 Clang 而不是 GCC (無論是使用a
、 Q
還是r
)進行編譯時,我確實得到了想要的結果:
movb 4(%esp), %ah
# my value ended up in %ah
我還嘗試用bh
、 ch
和dh
代替ah
,它們的每一種組合都會產生類似的結果。
我還嘗試編譯為 64 位而不是 32 位。 在那里,GCC 基本上仍然做同樣的錯誤:
movl %edi, %eax
# my value ended up in %al
並且 Clang 完全無法編譯Cannot encode high byte register in REX-prefixed instruction
除非我關閉了優化(我打開了LLVM bug #45865 ),在這種情況下,它最終確實在正確的位置獲得了值:
movb %dil, -1(%rsp)
movb -1(%rsp), %al
movb %al, -2(%rsp)
movb -2(%rsp), %ah
# my value ended up in %ah
這是我應該報告的 GCC 中的錯誤,或者這是不應該工作的東西,只是在 Clang 中偶然工作? 如果是后者,有沒有辦法做我想做的事,還是我必須滿足於自己從程序mov
的其他地方把它移到那里?
顯然,約束不允許選擇嵌套寄存器,但您可以在指令引用中添加一個h
修飾符。 這在Input Operands的文檔中有所提及。 例如,
void f(char x) {
char a;
__asm__ __volatile__(
"mov %0, %h1" :: "X"(x), "a"(a)
);
}
生產
f:
xorl %eax, %eax
mov 4(%esp), %ah
ret
我無法擺脫清除eax
的xor
。 我的猜測是代碼生成器將“%h1”解釋為設置了 8 位的 32 位字,而不是字符寄存器引用。 例如,這個:
char f(char x) {
char a;
__asm__ __volatile__(
"movb %0, %h1" :: "X"(x), "a"(a)
);
return a;
}
...編譯成相同的代碼,即使它返回\0
,不是很直觀。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.