2014-04-29 173 views
1

預先感謝您的時間!我目前正在製作一個迷你pascal編譯器。掃描,分析和語義分析正在工作,我正處於代碼生成階段。我遇到了一些我已經生成的代碼,我不完全理解它爲什麼不起作用。它可以編譯,但輸出完全關閉。我將首先鏈接示例程序,然後生成彙編代碼。英特爾奔騰彙編器x86彙編代碼生成

type recordType = record of { 
       x: int, 
       y: int 
       }; 

func a(x : int, y : int) : recordType 
    var p2 : recordType; 
    allocate p2; 
    p2.x = x; 
    p2.y = y; 
    return p2; 
end a 

var p1 : recordType; 
p1 = a(10,2); 

write p1.x/p1.y; 

由於彙編代碼是相當大的(因無優化一直沒有完成),我會爲功能的鏈接代碼,因爲我認爲問題出在那裏。如果您想要完整的示例,我會很樂意發佈它,但除非要求,否則我不會發送垃圾郵件。

的功能的彙編代碼如下所示:

a: 
    pushl %ebp 
    movl %esp, %ebp 
    lea -8(%ebp), %eax 
    pushl %eax 
    popl %eax 
    imul $8, %eax 
    pushl %eax 
    call malloc 
    addl $4, %esp 
    movl %eax, -8(%ebp) 
    lea -8(%ebp), %eax 
    pushl %eax 
    popl %eax 
    addl $4, %eax 
    pushl %eax 
    movl 12(%ebp), %eax 
    pushl %eax 
    popl %eax 
    popl %ebx 
    movl %eax, (%ebx) 
    lea -8(%ebp), %eax 
    pushl %eax 
    popl %eax 
    addl $0, %eax 
    pushl %eax 
    movl 8(%ebp), %eax 
    pushl %eax 
    popl %eax 
    popl %ebx 
    movl %eax, (%ebx) 
    movl -8(%ebp), %eax 
    pushl %eax 
    popl %eax 
    jmp aend 
aend: 
    movl %ebp, %esp 
    popl %ebp 
    ret 

現在你說什麼了。我知道有很多冗餘代碼,這是因爲我還沒有優化代碼。這就是說,我想談談使用的慣例。參數x和y根據它們的大小(int,bool和array是4個字節,其中記錄的總大小等於它們成員的大小的總和)被保存爲基址指針(%ebp)的偏移量+局部變量根據basepointer以-offset保存(params從+8開始,locals從-4開始)。請記住,AT & T style中的彙編程序使用慣例movl src,dst,這與常規彙編程序不同。

我認爲問題可能在於lea指令和movl之間的混合,或者根據basepointer的索引。無論如何,它可以編譯,並給我一個3的consisten結果,當它應該是5.我已經測試了我的部門,它似乎與「正常」整數工作。

任何幫助,非常感謝。提前致謝!

問候 馬格努斯

回答

0

因爲lea -8(%ebp),%eax由8計算的地址的指令imul $8,%eax乘以一個地址......爲什麼呢?代碼​​在堆棧指針下存儲%eax。所以這個價值不會存活很長時間!

代碼movl %eax,(%ebx)也存儲在堆棧指針下面,因爲%ebx現在包含有效地址-4(%ebp)。當%ebx包含有效地址-8(%ebp)時,第二次發生10行。

也許你需要做的是用subl $8,%espmovl %esp,%eax替換第三條指令。這真的會爲你的局部變量建立一個區域。