2013-12-16 3 views
1

Я написал простой код для понимания сборки. Это:Использование указателя EBP после вызова метода

int sum(int a, int b){ 
     int res = a+b; 
    } 

И в основной функции я вызываю функцию суммы. Так, и я получаю assemblercode (я только взять часть функции суммы здесь) 4

push ebp, 
    mov ebp, esp 
    sub esp, 16 
    mov eax, DWORD PTR[ebp + 12] 
    mov edx, DWORD PTR[ebp + 8] 
    add eax, edx 
    mov DWORD PTR [ebp-4], eax 
    mov eax, DWORD PTR [ebp-4] 
    leave 

и теперь на мои вопросы. У меня есть два вопроса: Во-первых, есть ли причина, по которой значения параметра суммы, например sum (5,4), занимаются в ebp + 12 и ebp + 8, а результат - в ebp-4? Почему мы это делаем? Всегда ли это то же самое или выбирается случайным образом?

Во-вторых, часть, в которой мы имеем:

mov DWORD PTR [ebp-4], eax 
    mov eax, DWORD PTR [ebp-4] 

почему мы делаем результат первого в EBP-4, а затем в EAX снова, прежде чем покинуть функцию? Есть ли причина?

+0

Чтобы быть в состоянии дать вам однозначный ответ, и есть один, я хотел бы попросить вас, чтобы сказать, что компилятор вы используете. – Rastikan

+0

Какая ОС и какой компилятор? – nrz

+0

вы объявили функцию 'int', но ничего не вернули –

ответ

2

Как правило, кадр стека создается в системах x86.

Вызывающий преобразует это в ...

push b 
push a 
call sum 

Поскольку каждый элемент помещается в стек, стек растет вниз. То есть регистр указателя стека уменьшается на четыре (4) байта (в 32-битном режиме), и элемент копируется в ячейку памяти, на которую указывает регистр стека.

На данный момент выдается инструкция «вызов», и теперь мы находимся в начале вызываемой процедуры. Если мы хотим получить доступ к нашим параметрам, мы можем получить доступ к ним как

[esp + 4] - parameter 'a' 
[esp + 8] - parameter 'b' 

Однако, это может получить неуклюжее после того как мы выкроить пространство для локальных переменных и прочего. Таким образом, мы используем регистр указателя стека в дополнение к регистру указателя стека. Однако мы хотим, чтобы регистр стека-указателя был установлен на наш текущий кадр, а не на предыдущую функцию. Таким образом, мы сохраняем старый в стеке (который изменяет смещения параметров в стеке), а затем копирует текущий регистр указателя стека в регистр указателя стека.

push ebp  ; save previous stackbase-pointer register 
mov ebp, esp ; ebp = esp 

Складывая все это вместе. Параметры доступны с помощью stackbase-указатель РЕГИСТР

[ebp + 12] - parameter 'b' 
[ebp + 8] - parameter 'a' 
[ebp + 4] - return address 
[ebp + 0] - saved stackbase-pointer register 

Источник: What is stack frame in assembly?

0

Вы можете найти эту информацию путем поиска ключевых слов, таких как:

  • призывающих конвенций
  • азЬсаИ
  • stdcall

В то же время в EAX будет передан параметр 16-битного слова с AX (и 32 бит один). Возврат также будет AX/EAX. 64-битный параметр (или 2 параметра будет в EDX: EAX) и возвращен с ним.Это для типичного соглашения о вызове FASTCALL (которое, как я считаю, использовал старый Паскаль)

Теперь для C/C++ fastcall обычно не используется (возможно, потому, что он не такой портативный). Большинство из них использовало стек, и именно здесь играет EBP. EBP, являющийся вашим указателем базового стека -4, -8, -12, является только указателем смещения в вашем локальном стеке, где параметр хранится и возвращается.

Вот несколько ссылок: http://en.wikibooks.org/wiki/X86_Disassembly/Calling_Convention_Examples http://en.wikipedia.org/wiki/X86_calling_conventions

Смежные вопросы