Куда именно (!) Указывает указатель стека на процессорах x86? К верхнему элементу или прямо за ним?
В некоторых руководствах говорится, что указатель стека указывает на верхний элемент стека:
+-------------+
| stack |
+-------------+
| top element | <-- esp
+-------------+
В других говорится, что он указывает прямо за ним, то есть на первый адрес памяти, который может быть записан при увеличении стека.
+-------------+
| stack |
+-------------+
| top element |
+-------------+ <-- esp
На этом немецком сайте википедии https://de.wikipedia.org/wiki/Register_(Computer) сказано, что обе версии существуют и что это зависит от архитектуры процессора.
Мой вопрос, как это на x86-процессорах? И зависит ли это также от операционной системы?
1 ответ
Допустим, вы находитесь в режиме 32b x86, и у вас есть память с адреса от 100 до 200, зарезервированная как стек (нереально, слишком мало, конфликтует с IVT, но подойдет для этого примера). В стеке уже есть некоторые значения, поэтому esp
160
Теперь "верхняя часть значения стека" занимает память по адресам 160, 161, 162 и 163 (четыре байта, потому что в режиме 32b одно значение в стеке имеет размер 32b = 4B), скажем, есть сохраненное значение 0xaabbccdd
,
Если вы сейчас делаете push 0x12345678
ЦП сначала вычтет 4 из esp
-> новый esp = 156; (160-4)
, И тогда он запишет значение 32b, разбитое в порядке байтов как четыре байта: mem[156] = 0x78, mem[157] = 0x56, mem[158] = 0x34, mem[159] = 0x12
,
Теперь, если вы будете выполнять mov eax,[esp]
, он будет загружать 32-битное значение из адреса 156, что означает, что он будет составлять 32-битное значение из четырех байтов по адресам 156, 157, 158, 159 в dword
значение 0x12345678.
Наконец, когда вы будете просматривать память в отладчике после нажатия, просматривая ее из ss:esp
адрес, он будет содержать эти байты (гекса):
0000009C: 78 56 34 12 DD CC BB AA ....
(0x9C = 156 = адрес, с которого начинается просмотр памяти). esp
указывает на первый байт значения, которое считается "вершиной стека".
Или когда вы переключаете вид памяти для отображения dword
Значения, чтобы избежать создания порядка байтов в голове, он покажет:
0000009C: 12345678 AABBCCDD ....