Правильно ли я понимаю стек в этом коде сборки Y86? - PullRequest
1 голос
/ 21 июня 2009

Я создал этот простой и бессмысленный код сборки (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)

Ответы [ 2 ]

2 голосов
/ 21 июня 2009

Насколько я могу судить, у вас все в порядке.

Один небольшой момент, который я могу сделать, состоит в том, что, вероятно, более интуитивно понятно писать адреса выше значения по этим адресам. То есть:

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

Причина в том, что диапазон адресов, охватывающий значение (0x2E, 0x2F, 0x30, 0x31), идет к следующему адресу 0x32.

Конечно, вы можете использовать обозначения, ожидаемые вашим учителем при сдаче экзамена.

0 голосов
/ 08 ноября 2012

Вы правильно поняли.

Что вы делаете, так это выполняете вызов функции, используя стандартные соглашения между вызывающим и вызываемым абонентами, создавая рамку для вызываемого. Затем вы выполняете простое нажатие и извлечение регистра, прежде чем вернуться к вызывающей стороне. Это абсолютно правильно, и ваше понимание верно (см. http://y86tutoring.wordpress.com/2012/10/31/functioning-stacks/ для деталей)

Все выглядит хорошо. Единственное предложение состоит в том, что вам не нужно определять слово 0x0000 в стеке. Простое определение метки стека сделало бы это.

...