上面的代碼片段是(IMO斷開的)AT & T語法中的x86_32程序集。
AT & T語法將大小後綴附加到每個操作數。
movl
表示32位操作數。 (L爲長)
movw
裝置16位操作數(W爲字)
movb
意味着一個8位操作數(b代表字節)
的操作數,以便顛倒,所以目的地是在右側和來源位於左側。
這與幾乎所有其他編程語言都是相反的。
寄存器名稱的前綴爲%
,以將它們與變量名稱區分開來。 如果寄存器被括號()
包圍,這意味着寄存器指向的內存地址被使用,而不是寄存器內部的值。
這很有意義,因爲EBP被用作指向棧幀的指針。
Stackframes用於訪問函數中的參數和局部變量。
而是寫的:mov eax, dword ptr [ebp+8]
(Intel語法)
AT & T語法將其列爲:movl 8(%ebp), %eax
(gas syntax)
這意味着:把爭辯的內存地址指向(EBP + 8 )轉換成eax。
這裏的翻譯:
.L13: <<-- label used as a jump target.
movl 8(%ebp), %eax <<-- p1, stored at ebp+8 goes into EAX
movl (%eax), %edx <<-- p1 is a pointer, EDX = p1->next
movl 12(%ebp), %ecx <<-- p2, stored at ebp+12 goes in ECX
movl (%ecx), %eax <<-- p2 is (again) a pointer, EAX = p2->next
movl 8(%ebp), %ecx <<-- ECX = p1
movl %eax, (%ecx) <<-- p2->next = p1->next
jmp .L19 <<-- jump to exit
...
.L19
movl %edx, %eax <<-- EAX is always the return value
<<-- return p1->data.
在所有函數的返回值被放入EAX寄存器x86上的許多調用約定。 (或EAX:EDX如果是INT64)
In散文:p1和p2是指向數據的指針,在這個數據指針指向指針。
此代碼看起來像它操縱鏈表。
p2->next
設置爲p1->next
。
除此之外,代碼片段看起來不完整,因爲p2->next
開頭的任何內容都不起作用,因此可能有更多的代碼沒有顯示。
除了令人困惑的AT & T語法外,它實際上是非常簡單的代碼。
在C代碼看起來像:
(void *)p2->next = (void *)p1->next;
注意,代碼是相當低效也沒有像樣的編譯器(或人)會產生這樣的代碼。
如下的等價會更有意義:
mov eax,[ebp+8]
mov ecx,[ebp+12]
mov eax,[eax]
mov [ecx],eax
jmp done
在AT & T和Intel語法的區別更多信息可以在這裏找到:http://www.ibm.com/developerworks/linux/library/l-gas-nasm/index.html
你確實是知道操作數的順序在AT&T語法中顛倒過來?所以最後一條語句是'MOV EAX,EDX',而不是相反。 – Johan
@CarlNorum它不是我...... – Joshua
@Johan這個例子中的每一行都是從教科書逐字寫出的 – Joshua