2009-06-21 3 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 |-------| 

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

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

+0

На самом деле я не знаю, что используется «обозначение»:/В этом примере я всегда, хотя 0x13 собирался быть сохранен в [0x2E, 0x2D, ​​0x2C, 0x2B], для меня это имело больше смысла. Это привело бы меня к другому вопросу, если бы кто-то ответил мне, что «у вас все в порядке»: Почему, черт возьми, мы оставляем пустой блок в [0x32, 0x31, 0x30, 0x2F]? –

+2

Это объясняет, почему вы проиллюстрировали это так же, как и вы, но обратите внимание, что стек только/растет/вниз (т. Е. Новый элемент ниже последнего), что не означает, что сами элементы также сохраняются в обратном порядке. A (4-байтовый) элемент в x всегда сохраняется в x, x + 1, x + 2, x + 3. Реверсирование этого для стека также означает, что вы не можете легко использовать адреса из стека в «нормальном» коде. Что касается пустого блока в нижней части стека: это является следствием того факта, что pushl v хранит v в% esp-4 вместо% esp.Конечно, во многих случаях вы можете избежать этого, изменив начальное значение% esp. – mweerden

0

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

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

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

+0

Добро пожаловать в переполнение стека! Благодарим за отправку ответа! Обязательно внимательно прочитайте [FAQ по самопомощи] (http://stackoverflow.com/faq#promotion). Также обратите внимание, что * требуется *, что вы публикуете отказ от ответственности каждый раз, когда вы ссылаетесь на свой собственный сайт/продукт. –