簡體   English   中英

如何讓 GCC 將 char 放入 ah/bh/ch/dh?

[英]How do I get GCC to put a char in ah/bh/ch/dh?

假設我有一些內聯程序集需要ahbhchdh中的特定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 (無論是使用aQ還是r )進行編譯時,我確實得到了想要的結果:

        movb    4(%esp), %ah
        # my value ended up in %ah

我還嘗試用bhchdh代替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的其他地方把它移到那里?

32 位 Godbolt 鏈接 64 位 Godbolt 鏈接

顯然,約束不允許選擇嵌套寄存器,但您可以在指令引用中添加一個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

我無法擺脫清除eaxxor 我的猜測是代碼生成器將“%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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM