Над ним находится предыдущий EBP (0012FF80
). Значение выше prev-EBP всегда является адресом возврата.
(Это, очевидно, предполагает двоичный файл без FPO и 32-битную Windows) 1 .
Если вы помните, пролог выглядит так:
push ebp ; back up the previous ebp on the stack
mov ebp, esp ; set up the new frame pointer
и когда вызывается функция, например,
call 0x00401000
Текущий EIP помещается в стек (используется как адрес возврата), поэтому стек после пролога выглядит следующим образом:
[ebp+0xc] ; contains parameter 1, etc
[ebp+0x8] ; contains parameter 0
[ebp+0x4] ; contains return address
[ebp] ; contains prev-EBP
Таким образом, для каждого %p
printf использует следующие 4 байта, начиная с [ebp+0xc]
(первый параметр %p
). В конце концов вы попадаете на предыдущее значение EBP, хранящееся в стеке, которое (0012FF80
), а затем следующее - Обратный адрес.
Обратите внимание, что эти адреса должны «иметь смысл», что они явно делают здесь (хотя это может быть не «понятно» для всех).
Re Q2) Стек растет. Таким образом, когда вы push eax
, 4 вычитается из esp
, тогда значение eax перемещается в [esp], эквивалентно в коде:
push eax
; <=>
sub esp, 4
mov [esp], eax
- Книга Написание безопасного кода , да?