2014-06-11 29 views
0

我正在編寫一個編譯器 - 或者看起來像這樣的東西 - 而且我正在生成簡單的部分,未優化的彙編代碼。在_start函數(x86 ASM)中寫入棧作爲局部變量

代碼工作,除了一兩件事。

我明白%esb%esp工作作爲一個函數調用如下:

Parameter #N  -> N*4+4(%ebp) 
Parameter 2  -> 12(%ebp) 
Parameter 1  -> 8(%ebp) 
Return Address  -> 4(%ebp) 
Old %ebp   -> (%ebp) 
Local Variable 1 -> -4(%ebp) 
Local Variable 2 -> -8(%ebp) and (%esp) 

但是,下面的代碼,這是從我的編譯器的輸出,在第一行的段錯誤,我試圖給-8(%esp)_start。在twice函數中執行同樣的操作不會導致段錯誤。

這似乎是在_start功能我不能存儲在堆棧上「局部變量」,我不知道我應該怎麼解決這個問題?

程序:

.section .data 
.section .text 
.globl _start 
.globl twice 
.type twice, @function 
twice: 
    pushl %ebp 
    movl %esp, %ebp 

    movl 8(%ebp), %eax 
    movl 8(%ebp), %ebx 
    addl %eax, %ebx 
    movl %ebx, -4(%ebp) 
    movl %ebx, %eax 
    movl %eax, -8(%ebp) 
    movl %eax, -8(%ebp) 
end_twice: 
    leave 
    ret 
_start: 
    movl $10, %eax 
    movl %eax, -8(%ebp) 
    movl $10, %eax 
    pushl %eax 
    call twice 
    addl $4, %esp 
    movl %eax, -8(%ebp) 
    movl %eax, %ebx 
    # Exit stuff. 
    movl $1, %eax 
    int $0x80 

原始輸入:

int twice(int x) 
{ 
    return x+x; 
} 

int main() 
{ 
    int x; 
    x = 10; 
    x = multiply(x); 
} 
+1

這是你的工作,如果你想用它來初始化'ebp'。注意你在'twice'中做了'mov%esp,%ebp',但'_start'中沒有這樣的事情。實際分配您嘗試使用的空間也是一個好主意(通常由'subl $ size,%esp'完成)。 – Jester

+0

編碼出「輸入」微代碼指令(這是一件好事)的等價物,這表明您可能也希望對「離開」指令也這樣做。 –

+0

初始化%ebp指針有竅門!謝謝你! –

回答

1

你會通常情況下,如果使用EBP作爲指向本地堆棧幀,而不是調用子之前寫在那裏的指向。相反,您只需推送到ESP,然後將其留給子設備以相應地設置EBP,以便您可以從之前推送到ESP的位置讀取。因此,如果使用「傳統」堆棧幀,則使用EBP是不正確的。

+0

你是對的。所以我現在所做的僅僅是使用'pushl'來推送值,而不是立即寫入堆棧。 –