2009-06-21 176 views
1

我已經創建了這個簡單且毫無意義的程序集(Y86)代碼,以瞭解在使用指令調用pushl,popl和ret時是否理解堆棧中發生的所有事情。我在這個Y86彙編代碼中正確理解堆棧嗎?

就像我說的,這段代碼沒有意義,它只是用於測試/學習的目的。雖然,所有的內存地址都是正確的(有希望的)計算出來的,並不是隨機的。

的彙編代碼如下:

 | .pos 0 
0x00 | irmovl Stack, %esp 
0x06 | rrmovl %esp, %ebp 
0x08 | irmovl $5, %eax 
0x0E | call func 
0x13 | halt 
0x14 | func: 
0x14 | pushl %ebp 
0x16 | rrmovl %esp, %ebp 
0x18 | pushl %eax 
0x1A | popl %eax 
0x1C | popl %ebp 
0x1E | ret 
    | .pos 50 
0x32 | Stack: .long 0 

以下是我最好畫一個堆棧並解釋每個步驟(指令)不與堆棧。請注意,我使用SP和BP來分別引用%esp和%ebp,因爲它們被大量使用並使得它更易於閱讀。

我想知道的是,如果我得到了一切正確或如果我錯過了任何東西。請隨意複製/粘貼任何你想要的,並修復你的答案中的一些步驟。

另請注意,我對此的理解非常重要,我有一個考試周一我需要做好準備,我希望能給你最好的答案。根據你的回答,我可能(或不)有一些相關的問題,我們會在評論部分注意。

- INSTRUCTION: irmovl Stack, %esp 
- INSTRUCTION: rrmovl %esp, %ebp 
    1) Point %esp (SP) and %ebp (BP) to Stack 

    | ... | 
0x2E |-------| 
    |  | 
0x32 |-------| <--- SP & BP 

- INSTRUCTION: irmovl $5, %eax 
    1) Sets %eax = 5 

- INSTRUCTION: call func 
    1) Decrements SP by 4 (0x32 -> 0x2E) 
    2) Saves return address (0x13) in memory location pointed by SP (0x2E) 
    3) Jumps to "func" memory address (0x14) 

    | ... | 
0x2A |-------| 
    | 0x13 | 
0x2E |-------| <--- SP 
    |  | 
0x32 |-------| <--- BP 

- INSTRUCTION: pushl %ebp 
    1) Decrements SP by 4 (0x2E -> 0x2A) 
    2) Saves BP value (0x32) in memory location pointed by SP (0x2A) 

    | ... | 
0x26 |-------| 
    | 0x32 | 
0x2A |-------| <--- SP 
    | 0x13 | 
0x2E |-------| 
    |  | 
0x32 |-------| <--- BP 

- INSTRUCTION: rrmovl %esp, %ebp 
    1) Sets BP = SP (0x32 -> 0x2A) 

    | ... | 
0x26 |-------| 
    | 0x32 | 
0x2A |-------| <--- SP & BP 
    | 0x13 | 
0x2E |-------| 
    |  | 
0x32 |-------| 

- INSTRUCTION: pushl %eax 
    1) Decrements SP by 4 (0x2A -> 0x26) 
    2) Saves %eax value (5) in memory location pointed by SP (0x26) 

    | ... | 
0x22 |-------| 
    | 5 | 
0x26 |-------| <--- SP 
    | 0x32 | 
0x2A |-------| <--- BP 
    | 0x13 | 
0x2E |-------| 
    |  | 
0x32 |-------| 

- INSTRUCTION: popl %eax 
    1) Saves value (5) in memory location pointed by SP (0x26) in %eax 
    2) Increments SP by 4 (0x26 -> 0x2A) 

    | ... | 
0x22 |-------| 
    | 5 | 
0x26 |-------| 
    | 0x32 | 
0x2A |-------| <--- SP & BP 
    | 0x13 | 
0x2E |-------| 
    |  | 
0x32 |-------| 

- INSTRUCTION: popl %ebp 
    1) Saves value (0x32) in memory location pointed by SP (0x2A) in %ebp 
    2) Increments SP by 4 (0x2A -> 0x2E) 

    | ... | 
0x22 |-------| 
    | 5 | 
0x26 |-------| 
    | 0x32 | 
0x2A |-------| 
    | 0x13 | 
0x2E |-------| <--- SP 
    |  | 
0x32 |-------| <--- BP 

- INSTRUCTION: ret 
    1) Jumps to memory address (0x13) in memory location pointed by SP (0x2E) 
    2) Increments SP by 4 (0x2E -> 0x32) 

回答

2

據我可以告訴你已經得到它的權利。

我可以做的一點是,在這些地址上寫入地址值可能更直觀。那就是:

0x2E |-------| 
    | 0x13 | 
0x32 |-------| 

原因是,覆蓋值的地址範圍(0x2E0x2F0x300x31)變爲朝向所述下一個地址0x32

當然,您可能需要使用老師在考試時所期望的符號。

+0

其實我不知道使用的「符號」:/在這個例子中,我總是儘管0x13將被保存在[0x2E,0x2D,0x2C,0x2B],它對我來說更有意義。如果有人回答說「你知道了」,那麼這會導致我另一個問題:爲什麼我們會在[0x32,0x31,0x30,0x2F]處留下空白塊? – 2009-06-21 12:14:14

+2

這就解釋了爲什麼你要這樣說明,但注意只有/增長/向下的堆棧(即一個新的元素低於最後一個)並不意味着元素本身也被向後存儲。 x處的(4字節)元素始終存儲在x,x + 1,x + 2,x + 3處。爲棧反轉這也意味着你不能在「正常」代碼中輕鬆使用堆棧中的地址。關於堆棧底部的空白塊:這是pushl v在%esp-4而不是%esp存儲v的結果。當然,在很多情況下,您可以通過更改%esp的初始值來避免這種情況。 – mweerden 2009-06-21 17:40:36

0

你說得對。

你在做什麼是使用標準的主叫方 - 被叫方慣例進行函數調用,爲被叫方創建一個幀。然後在返回給調用者之前,執行一個簡單的推送和註冊。這是完全正確的,你的理解是正確的(詳見http://y86tutoring.wordpress.com/2012/10/31/functioning-stacks/

一切看起來不錯。只有建議是你不需要在堆棧上定義一個0x0000字。簡單地定義Stack標籤就可以做到。