1

この単純で無意味なアセンブリ (Y86) コードを作成して、命令 call、pushl、popl、および ret が使用されたときにスタックで起こっていることをすべて理解しているかどうかを確認しました。

私が言ったように、このコードは無意味です。テスト/学習目的のためだけです。ただし、すべてのメモリ アドレスは正しく (期待どおり) 計算されており、ランダムではありません。

アセンブリ コードは次のとおりです。

     | .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)
4

2 に答える 2

2

私が言える限りでは、あなたは大丈夫です。

私が言える小さなポイントは、それらのアドレスの値の上にアドレスを書く方がおそらくより直感的だということです。あれは:

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

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

もちろん、試験を行う際に、教師が期待する表記法を使用することもできます。

于 2009-06-21T05:14:22.230 に答える
0

あなたはそれを正しく理解しました。

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

すべてが良さそうです。唯一の提案は、スタックに 0x0000 ワードを定義する必要がないことです。単純に Stack ラベルを定義するだけで済みます。

于 2012-11-08T03:18:32.523 に答える