Описание команды push ebp и pop ebp в сборке
Я использовал стек в сборке, но у меня не было представления о push ebp и pop ebp.
.intel_syntax noprefix
.include "console.i"
.text
askl: .asciz "Enter length: "
askb: .asciz "Enter breadth: "
ans: .asciz "Perimeter = "
_entry:
push ebp # establishing stack-frame
mov ebp, esp
sub esp, 12
Prompt askl
GetInt [ebp-4] # length
Prompt askb
GetInt [ebp-8] # breadth
mov eax, [ebp-4] # eax = l
add eax, [ebp-8] # eax = l + b
add eax, eax # eax = 2 * (l + b)
mov [ebp-12], eax
Prompt ans
PutInt [ebp-12]
PutEoL
mov esp, ebp
pop ebp # unwinding stack-frame
ret
.global _entry
.end
Ответы
Ответ 1
Я не уверен, что это ваше сомнение, но, может быть, вам интересно об этом:
push ebp
mov ebp, esp
sub esp, 12
Первые две строки известны как функция сборки пролога. Он сохраняет предыдущий базовый указатель (ebp) и устанавливает базовый указатель, поскольку он был вершиной стека. Это означает, что все содержимое стека сохраняется в стеке, поэтому функция может нажать/поместить в стек.
Строка sub esp,12
сохраняет пространство для локальных переменных в функции.
В конце у вас есть:
mov esp, ebp
pop ebp
ret
Это обратный пролог, поэтому предыдущий контекст может быть восстановлен.
Это ваши сомнения?:)
Ответ 2
ebp
известен как базовый указатель или указатель кадра. При входе в вашу функцию вы ее нажимаете (чтобы сохранить значение для вызывающей функции). Затем скопируйте esp
, указатель стека, в ebp
, чтобы ebp
теперь указывал на фрейм стека вашей функции. В конце вашей функции вы затем поместите ebp
, чтобы восстановить значение вызывающей функции.
Для уточнения того, что происходит, инструкция push
помещает значение из указанного регистра (ebp
в этом случае) в стек и уменьшает указатель стека на соответствующую сумму. Операция pop
противоположна - она увеличивает указатель стека и берет значение из стека и помещает его в указанный регистр.