Pushl %esp обновляет ESP до или после сохранения?

pushl Инструкция Y86 уменьшает указатель стека на 4 и записывает значение регистра в память. Так что не понятно, что должен делать процессор при выполнении инструкции pushl %esp, поскольку передаваемый регистр изменяется той же инструкцией. Возможны два возможных события:

(1) толкнуть первоначальное значение %espили (2) нажмите уменьшенное значение %esp,

В свете этого, как мы можем изменить этот код-эквивалент pushl REG чтобы учесть и учесть эти неоднозначности (поскольку REG может быть%esp, как и любой другой регистр)?:

subl $4,%esp                   Decrement stack pointer
movl REG,(%esp)                Store REG on stack

Точно так же инструкция popl %esp может установить %esp к значению, считанному из памяти, или к увеличенному указателю стека. Как можно изменить этот код, чтобы учесть эти двусмысленности?:

movl (%esp),REG                Read REG from stack
addl $4,%esp                   Increment stack pointer

1 ответ

y86 основан на x86. Запись справочного руководства по набору команд x86 дляpush говорит (правильно):

Инструкция PUSH ESP выдвигает значение регистра ESP в том виде, в каком оно существовало до выполнения инструкции.

А такжеpop:

Инструкция POP ESP увеличивает указатель стека (ESP) до того, как данные в старой вершине стека будут записаны в место назначения.

Так что в pop %esp В этом случае приращение теряется. Эта последовательность имеет тот же эффект, хотя большинство реальных процессоров, вероятно, загружаются во временную внутреннюю память вместо того, чтобы фактически использовать обновленное значение ESP в режиме адресации.

add   $4, %esp
movl  -4(%esp), %esp

Но pop %esp делает это без обновления FLAGS и без возможности обработки прерываний или сигналов между add и mov. (Отдельная последовательность добавления / перемещения не безопасна в тех случаях, когда что-либо ниже текущего %esp может быть асинхронно перезаписан обработчиком прерываний.)


Предположительно y86 делает то же самое, что и x86. Вы можете легко (и должны) проверить с помощью отладчика, как ваш любимый симулятор y86 справится с этим угловым делом. push %esp легко проверить, посмотрев на память (или добавив pop %eax после этого).

Одновременное тестирование обоих может привести к путанице, и если всплывающее значение совпадает со старым указателем стека, вы не сможете увидеть разницу. Вероятно, нажмите 0 (или хранить 0 в (%esp)), затем pop %esp и посмотреть, какое значение есть в реестре с помощью отладчика. (Не имеет значения, если ваш код после этого падает, вы просто используете отладчик.)

Я не проверял, поддерживает ли y86 push $0 или же movl $0, (%esp) как х86. Я думаю, это будет immovl $0, (%esp) если это поддерживается (немедленно к памяти). Если нет, то обнулите регистр и нажмите его.

Другие вопросы по тегам