簡體   English   中英

如何在Intel語法中將匯編中的立即值傳遞給shr?

[英]How can I pass an immediate value to shr in assembly in Intel syntax?

根據該引用該引用shr指令支持通過CL寄存器和立即值移位1 但是,我似乎無法立即獲得工作價值; 當我有這個代碼時:

#include <stdint.h>

int main() {
  uint64_t v = 15;
  asm ("shr %[v], $0x04\t\n"
       : [v] "+r" (v)
       :
       : "cc"
       );
  return v;
}

我收到此錯誤消息:

$ gcc -masm=intel foo.c
foo.c: Assembler messages:
foo.c:5: Error: operand size mismatch for `shr'

如何將立即值傳遞給shr (不將其加載到CL ,我關心它,因為我正在針對寄存器壓力瓶頸進行優化)。

您正在使用具有Intel匯編語法的指南。 GNU程序集(GAS)使用AT&T語法,它具有操作數的逆序。 改變他們的順序似乎做得很好:

uint64_t v = 0xffff;
asm ("shr $0x04, %[v]\n"
   : [v] "+r" (v)
   :
   : "cc"
   );
printf("%llx", v);        // 0xfff

(您也可以用shrq替換shr以顯式使用64位操作數)

如果您仍然希望像使用-masm=intel一樣使用Intel語法,則必須從立即值中刪除美元符號:

asm ("shr %[v], 4\n"
     ...)

如果你使用-masm=intel ,它會激活.intel_syntax noprefix Immediates不再采用$前綴。 (但對於地址,您需要OFFSET symbol )。 無論如何,不​​要使用$

顯然,如果你只是想要一個班次,你應該用C代替內聯asm https://gcc.gnu.org/wiki/DontUseInlineAsm (您可以屏蔽移位計數以避免UB的移位計數太高,例如旋轉: C ++中循環移位(旋轉)操作的最佳實踐


但是如果你想將它用作需要內聯asm的東西的一部分,那么你可以這樣做,以允許旋轉計數為C中的變量(在cl )或常量(立即)。我使用了"cJ"允許0-63立即數操作數( J )的約束 ,或rcx/ecx/cx/clc約束)中的寄存器操作數。 (特別是在cl ,因為我轉向(uint8_t)

另外,我使用b修飾符來覆蓋大小,以防你想要在轉換之前使用整個rcx作為其他東西的命名輸入。 (參見gcc文檔中的6.45.2.8 x86操作數修飾符 )。

有關某些指南,另請參閱標記wiki。

我使用https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Multiple-assembler-dialects-in-asm-templates來使用AT&T或Intel語法模式正確編譯和匯編。

Godbolt編譯器資源管理器中 ,您可以看到這與gcc一起使用,但是對於inline-asm,clang與-masm=intel無法正常工作。 它仍然替換為%rdi而不是rdi並且無法組裝。

static inline uint64_t shr (uint64_t v, unsigned c)
{
    // %b[c] is cl even if %[c] is ecx or whatever.
    asm ("shr  {%b[c],%[v] | %[v],%b[c]}"
         : [v] "+r" (v) 
         : [c] "cJ" ((uint8_t)c));  // the cast gets this to use cl
    return v;
}

uint64_t shr_variable(uint64_t v, int c) {
    return shr(v, c);
}

    mov     rax, rdi
    mov     ecx, esi
    shr   rax,cl
    ret


uint64_t shr_const(uint64_t v) {
    return shr(v, 13);
}

    mov     rax, rdi
    shr   rax,13
    ret

將其與純C進行比較,使用-march=haswell

// can use SHRX with BMI2 available.  And can optimize much better
uint64_t shr_variable_purec(uint64_t v, unsigned c) {
    //c &= 63;  // optional, compiles to zero instructions on x86 because shr and shrx already do this.
    return v >> c;
}

    shrx    rax, rdi, rsi
    ret

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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