對於娛樂,我正在學習GNU擴展程序集,使用帶有32位Linux目標的x86的AT & T語法。我剛剛花了最後三個小時編碼兩個可能的解決方案,以交換兩個整數變量a
和b
的值,我的解決方案都不能完全解決我的問題。首先,讓我們來看看我的TODO障礙在一些細節:如何編寫一個內嵌gnu擴展程序集的短塊來交換兩個整數變量的值?
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);
}
閱讀this 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
既然你傳遞寄存器你可以只要做'xchg%0,%1'。使用移動只需要1個臨時寄存器。將%0複製到該寄存器。然後將%1複製到%0,然後將臨時寄存器複製到%1。臨時將需要列在clobber列表中 –
另請參見XOR交換算法https://en.wikipedia.org/wiki/XOR_swap_algorithm –
您現有的行內彙編還存在問題,即a和b都是輸入和輸出。所以** both **應該使用讀寫約束''+ r「' –