Куда это нажимается?
esp - 4
.Точнее:
esp
вычитается из 4 - , значение увеличивается до
esp
pop
, и наоборот.
System V ABI сообщает Linux, чтобы rsp
указывал на разумное расположение стека при запуске программы: Каково состояние регистра по умолчанию при запуске программы (asm, linux)? что и какВы должны обычно использовать.
Как вы можете нажать регистр?
Пример минимального GNU GAS:
.data
/* .long takes 4 bytes each. */
val1:
/* Store bytes 0x 01 00 00 00 here. */
.long 1
val2:
/* 0x 02 00 00 00 */
.long 2
.text
/* Make esp point to the address of val2.
* Unusual, but totally possible. */
mov $val2, %esp
/* eax = 3 */
mov $3, %ea
push %eax
/*
Outcome:
- esp == val1
- val1 == 3
esp was changed to point to val1,
and then val1 was modified.
*/
pop %ebx
/*
Outcome:
- esp == &val2
- ebx == 3
Inverses push: ebx gets the value of val1 (first)
and then esp is increased back to point to val2.
*/
Выше вклGitHub с выполняемыми утверждениями .
Зачем это нужно?
Это правда, что эти инструкции могут быть легко реализованы через mov
, add
иsub
.
Они считают, что они существуют, потому что эти комбинации инструкций встречаются так часто, что Intel решила предоставить их нам.
Причина, по которой эти комбинации встречаются так часто,что они позволяют легко сохранять и восстанавливать значения регистров в памяти временно, такони не перезаписываются.
Чтобы понять проблему, попробуйте скомпилировать код на C вручную.
Основная трудность - решить, где будет храниться каждая переменная.
В идеале все переменные должнывписывается в регистры, которые являются самой быстрой памятью для доступа (в настоящее время примерно на 100x быстрее , чем RAM).
Но, конечно, мы можем легко иметь больше переменных, чем регистров, особенно для аргументоввложенные функции, поэтому единственным решением является запись в память.
Мы могли бы записать любой адрес памяти, но, поскольку локальные переменные и аргументы вызовов и возвращений функций вписываются в хороший шаблон стека, который предотвращает фрагментация памяти , это лучший способ справиться с этим.Сравните это с безумием написания распределителя кучи.
Затем мы позволим компиляторам оптимизировать распределение регистров для нас, так как это завершает NP, и является одной из самых сложных частей написания компилятора.Эта проблема называется распределение регистров , и она изоморфна раскраске графов .
Когда распределитель компилятора вынужден хранить вещи в памяти вместо просто регистров, чтоизвестен как разлив .
Это сводится к одной инструкции процессора или это более сложный?
Все, что мы знаем навернякав том, что Intel документирует инструкции push
и pop
, поэтому они являются одной инструкцией в этом смысле.
Внутренне, она может быть расширена до нескольких микрокодов, один для изменения esp
и один для выполненияпамяти ввода-вывода и занимают несколько циклов.
Но также возможно, что один push
быстрее, чем эквивалентная комбинация других инструкций, поскольку он более конкретен.
Этов большинстве случаев документально подтверждено: