簡體   English   中英

如何編寫一個簡短的內聯gnu擴展程序集塊來交換兩個整數變量的值?

[英]How to write a short block of inline gnu extended assembly to swap the values of two integer variables?

為了娛樂,我正在學習針對32位Linux目標使用針對x86的AT&T語法的gnu擴展程序集。 我剛剛花了最后三個小時來編寫兩個可能的解決方案,以應對交換兩個整數變量ab的值的挑戰,但是我的解決方案都不能完全解決我的問題。 首先,讓我們更詳細地了解我的TODO障礙:

int main()
{
    int a = 2, b = 1;
    printf("a is %d, b is %d\n", a, b);
    // TODO: swap a and b using extended assembly, and do not modify the program in any other way
    printf("a is %d, b is %d\n", a, b);
}

閱讀此HOWTO之后 ,我編寫了以下內聯擴展匯編代碼。 這是我第一次嘗試交換整數:

asm volatile("movl %0, %%eax;"
    "movl %1, %%ecx;"
    "movl %%ecx, %0;"
  : "=r" (a)
  : "r" (b)
  : "%eax", "%ecx");

asm volatile("movl %%eax, %0;"
  : "=r" (b)
  : "r" (a)
  : "%eax", "%ecx");

我的理由是要設置a = b,我需要一個與程序集分離的擴展程序集調用,以設置b = a。 因此,我編寫了兩個擴展程序集調用,編譯了我的代碼,即gcc -m32 asmPractice.c,並運行了a.out。 結果如下:

a是2,b是1

a是1,b是1

看到這不能正常工作后,我決定合並兩個擴展的匯編程序調用,並寫成這樣:

asm volatile("movl %0, %%eax;"
    "movl %1, %%ecx;"
    "movl %%ecx, %0;"
    "movl %%eax, %1;"
  : "=r" (a)
  : "r" (b));

重新編譯和鏈接后,我的代碼仍然無法正確交換兩個值。 你自己看。 這是我的結果:

a是2,b是1

a是1,b是1

以下是評論中的一些解決方案:

解決方案#0(最佳選擇): https : //gcc.gnu.org/wiki/DontUseInlineAsm
甚至零指令的解決方案也無法克服常數傳播,以及涉及gcc知道任何有關值的任何其他優化。 這也迫使編譯器此時將兩個變量同時保存在寄存器中。 在考慮使用inline-asm而不是buildins / intrinsics時,請始終牢記這些缺點。

解決方案#1:x86 xchg ,沒有臨時寄存器,並且可以在AT&T和Intel語法模式下使用。 成本與大多數Intel CPU上的3 mov指令相同,而在某些AMD上的成本僅為2 uops。

asm("xchg %0, %1;" : "+r" (a), "+r" (b));

解決方案2:僅使用GNU C內聯asm約束。 (獎金:可移植到所有架構)

asm("" : "=r" (a), "=r" (b) : "1" (a), "0" (b));

查看在Godbolt編譯器資源管理器上運行的所有三種解決方案,包括擊敗優化的示例:

int swap_constraints(int a, int b) {
    asm("" : "=r" (a), "=r" (b) : "1" (a), "0" (b));
    return a;
}

// Demonstrate the optimization-defeating behaviour:
int swap_constraints_constants(void) {
  int a = 10, b = 20;
  return swap_constraints(a, b) + 15;
}

swap_constraints_constants:
    movl    $10, %edx
    movl    $20, %eax
    addl    $15, %eax
    ret

與純C交換:

swap_noasm_constants:
    movl    $35, %eax    # the add is done at compile-time, and `a` is optimized away as unused.
    ret

暫無
暫無

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

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