源碼:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int result = 0;
int input = 1;
__asm__ __volatile__ ("addl %2,%0":"=r"(result): "r"(result),"r"(input));
printf("The result = %d\n",result);
return 0;
}
反彙編:
0x00401343 movl $0x0,0x1c(%esp)
0x0040134B movl $0x1,0x18(%esp)
0x00401353 mov 0x1c(%esp),%eax
0x00401357 mov 0x18(%esp),%edx
0x0040135B add %edx,%ebx #這裏ebx的內容是不確定的
0x0040135D mov %ebx,0x1c(%esp)
按照預計,應該會把result和input都放到寄存器中,如result放到edx,input放到eax中。然後執行addl %eax,%edx.但是反彙編的結果是addl %edx,%ebx。也就是addl的目的操作數一直是ebx。而ebx中是一個不確定的值,所以結果一直不對。
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
在上面的代碼中不能確保輸出參數result和第一個輸入參數result一定被放在同一個寄存器中了,所以下面用了一個比較穩妥的方法。使用佔位符,保證他倆存在一個register中。
0x00401343 movl $0x0,0x1c(%esp)
0x0040134B movl $0x1,0x18(%esp)
0x00401353 mov 0x1c(%esp),%edx
0x00401357 mov 0x18(%esp),%eax
0x0040135B mov %edx,%ebx
0x0040135D add %eax,%ebx
0x0040135F mov %ebx,0x1c(%esp)
因爲使用的"r",編譯器會自己安排通用寄存器來放置變量。可見開始的時候,result被放在edx中。後來應該使用佔位符,使得第一個輸入參數和輸出參數使用同一個寄存器。從倒數第2,3條指令中可見,它將edx中的內容mov到ebx中。然後再執行addl指令。
所以這裏考慮,是不是編譯器進行優化或者是規定了擴展內聯彙編中輸出變量默認存在ebx中?