我已經創建了這個簡單且毫無意義的程序集(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)
其實我不知道使用的「符號」:/在這個例子中,我總是儘管0x13將被保存在[0x2E,0x2D,0x2C,0x2B],它對我來說更有意義。如果有人回答說「你知道了」,那麼這會導致我另一個問題:爲什麼我們會在[0x32,0x31,0x30,0x2F]處留下空白塊? – 2009-06-21 12:14:14
這就解釋了爲什麼你要這樣說明,但注意只有/增長/向下的堆棧(即一個新的元素低於最後一個)並不意味着元素本身也被向後存儲。 x處的(4字節)元素始終存儲在x,x + 1,x + 2,x + 3處。爲棧反轉這也意味着你不能在「正常」代碼中輕鬆使用堆棧中的地址。關於堆棧底部的空白塊:這是pushl v在%esp-4而不是%esp存儲v的結果。當然,在很多情況下,您可以通過更改%esp的初始值來避免這種情況。 – mweerden 2009-06-21 17:40:36