2009-06-21 5 views
1

この単純で無意味なアセンブリ(Y86)コードを作成して、命令の呼び出し時にスタック内で起こっていることをすべて理解しているかどうかを確認しました。この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 

次のスタックを描き、各ステップ(命令)がスタックに何をするかを説明するために私の最善の方法です。 %espと%ebpを参照するのにSPとBPを使用していたことに注意してください。なぜなら、それらは多く使われて読みやすくなります。

私が知りたいのは、上記のすべてが上にあるか、私が何かを逃した場合です。自由にコピー/ペーストして、あなたの答えにいくつかのステップを修正してください。

また、私の理解は非常に重要なので、私は準備が必要な月曜日の試験があります。私はあなたに私が与えることができる最高の答えがほしいと思います。あなたの答えに応じて、コメント欄で気をつけなければならないいくつかの関連する質問があるかもしれません。

- 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

限り、私はそれが大丈夫だと言うことができます。

私が作ることができる短所の1つは、おそらくそれらのアドレスに値より上のアドレスを書く方が直感的であるということです。すなわち:

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

理由は、値をカバーするアドレス範囲(0x2E0x2F0x300x31)が次のアドレス0x32に向かって進むことです。

もちろん、試験を行うときに先生が期待している表記法を使用したい場合があります。

+0

実際に私は使用される "表記法"を知らない:/その例では、私は常に0x13が[0x2E、0x2D、0x2C、0x2B]に保存されるだろうが、それはちょうど私にとって意味がある。誰かが私に「あなたは大丈夫だ」と答えると、これは別の質問につながります。なぜ[0x32、0x31、0x30、0x2F]に空白のブロックを残しますか? –

+2

これはあなたがそのように説明した理由を説明しますが、スタックは/ grow/downwards(つまり、新しい要素が最後より下にある)のみであり、要素自体も後方に格納されているわけではありません。 xの(4バイト)要素は、常にx、x + 1、x + 2、x + 3に格納されます。スタックのためにこれを逆にすることは、スタックからのアドレスを "普通"のコードで簡単に使用できないことを意味します。スタックの一番下にある空のブロックについては、これはpushl vが%espではなく%esp-4にvを格納しているという結果です。もちろん、多くの場合、%espの初期値を変更することでこれを避けることができます。 – mweerden

0

あなたは正しいです。

あなたがやっていることは、標準の呼び出し元呼び出し先の規則を使用して関数呼び出しを実行し、呼び出し先のフレームを作成することです。次に、呼び出し元に戻る前に、レジスタの単純なプッシュ/ポップを実行します。これは完全に正しいですし、あなたの理解は正しいです(詳細については、http://y86tutoring.wordpress.com/2012/10/31/functioning-stacks/を参照してください)

すべてがうまく見えます。スタック上に0x0000ワードを定義する必要はないということだけをお勧めします。単純にStackラベルを定義するだけで済みます。

+0

ようこそスタックオーバーフロー!あなたの答えを投稿してくれてありがとう! [自己プロモーションに関するよくある質問](http://stackoverflow.com/faq#promotion)をよく読んでください。また、自分のサイト/製品にリンクするたびに免責条項を掲示することが必須*であることにも注意してください。 –

関連する問題