2013-10-13 48 views
0

作爲一項任務,我必須讀取彙編代碼並編寫它的高級C程序。這種情況下的結構是switch語句,因此對於每種情況,彙編代碼都將轉換爲C代碼中的情況。以下只是其中一例。如果你能幫助我解釋這一點,它應該讓我更好地理解其餘的案例。如何解釋這個IA32彙編代碼

p1 is in %ebp+8 
p2 is in %ebp+12 
action is in %ebp+16 
result is in %edx 

... 
.L13: 
    movl 8(%ebp), %eax # get p1 
    movl (%eax), %edx  # result = *p1? 
    movl 12(%ebp), %ecx # get p2 
    movl (%ecx), %eax  # p1 = *p2 
    movl 8(%ebp), %ecx # p2 = p1 
    movl %eax, (%ecx)  # *p1 = *p2? 
    jmp .L19    #jump to default 
... 
.L19 
    movl %edx, %eax  # set return value 

當然,這些評論是我加入來試圖理解它的,除了它讓我更加困惑。這是否意味着交換?可能不會;格式會有所不同。第二和第六行真的發生了什麼?爲什麼%edx只是如此早地改變一次,如果它是返回值?請回答一些準則來解釋此代碼。

+0

你確實是知道操作數的順序在AT&T語法中顛倒過來?所以最後一條語句是'MOV EAX,EDX',而不是相反。 – Johan

+0

@CarlNorum它不是我...... – Joshua

+0

@Johan這個例子中的每一行都是從教科書逐字寫出的 – Joshua

回答

4

上面的代碼片段是(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

+0

謝謝你的回答。您的評論與我的評論非常相似,所以我有正確的想法。通過將「* p1」劃分爲「p1->下一個」,我想我可以更好地理解這個案例和後續案例。 – Joshua

+0

是的,你在哪裏非常接近,當然是逆轉源和目的地讓你失望。除此之外,你釘了它。 – Johan