Доступ к фреймам стека на языке ассемблера

Я новичок в сборке, и тут я наткнулся на эту статью

он говорит, что этот код

void MyFunction()
{
  int a, b, c;
  a = 10;
  b = 5;
  c = 2;

эквивалентно этому

push ebp     ; save the value of ebp
mov ebp, esp ; ebp now points to the top of the stack
sub esp, 12  ; space allocated on the stack for the local variables
mov [ebp -  4], 10  ; location of variable a
mov [ebp -  8], 5   ; location of b
mov [ebp - 12], 2   ; location of c

Согласно этому видео, чтобы получить доступ к значению стека над указателем базы, мы должны добавлять. Если он ниже указателя, мы должны вычесть. В приведенном выше примере они вычли что-то из базового указателя, чтобы переместить местоположение необходимых переменных, что противоречит тому, что указано в видео.

Что я пропустил? Я знаю, что sub esp, 12 выделяет место для локальных переменных, поэтому я имею в виду, что EBP ниже этого распределения, поэтому я думаю, что оно должно быть [ebp + something], а не минусом.

Итак, когда он сделал этот sub esp, 12, именно так выглядит стек.

            ESP is here
|     2    | Ebp + 12
|     5    | Ebp + 8
|     4    | Ebp + 4
|          | Old EBP value

Статья была неправильной, или я неправильно ее истолковал?


person srh snl    schedule 22.05.2013    source источник


Ответы (2)


Причина использования ebp в том, что esp изменится, например передача аргументов подпрограмме. Таким образом, ваш ebp позволит вам получить доступ к той же переменной, используя одно и то же смещение, независимо от того, куда esp указывает в этот момент.

Когда вы помещаете значения в стек, его значение уменьшается; увеличивается, когда вы поп.

Код вычитает 12 (4 * 3), чтобы освободить место для 3 32-битных (4 байтовых) целых чисел. Ebp указывает на "дно", где раньше был esp. Таким образом, вы получаете доступ к переменной, используя отрицательное смещение, например эбп-4. Итак, ваша картина неверна: ebp + Независимо от того, что указывает на то, с чем ваш код не должен играть.

     BEFORE

     lower address
     |
     |<--------------  esp (=ebp after mov ebp, esp)
     |
     | 
     higher address


     AFTER mov ebp, esp; sub esp, 12

     lower address
     |<--------------  esp
     |
     |
     |<--------------  ebp
     |
     | 
     higher address


     AFTER mov [ebp-4], 10 ecc.

     lower address
     | 2  <--------------  esp
     | 5
     | 10
     |<--------------  ebp
     |
     | 
     higher address

В этот момент [esp] получит [ebp-12], т.е. 2.

person ShinTakezou    schedule 22.05.2013
comment
Так что можно с уверенностью сказать, что то, что было упомянуто в видео, неверно? Я уже понимаю концепцию стека, но когда я посмотрел видео, я был сбит с толку. Согласно видео, чтобы получить доступ к значению или чему-либо выше указателя Base, вы должны что-то добавить в EBP. чтобы получить доступ к чему-либо, находящемуся ниже базового указателя, мы должны вычесть из EBP. ?? - person srh snl; 22.05.2013
comment
Я сейчас не вижу видео; Предположим, что вышесказанное означает уменьшение адреса, ответ очевиден: чтобы получить доступ к чему-то, что предшествует (это выше), куда указывает указатель, вы должны уменьшить указатель. И наоборот, вы должны увеличить его. (Непонятно значение from в вашем для доступа к чему-либо снизу ...) - person ShinTakezou; 22.05.2013
comment
Все в порядке. Кроме того, во всей статье, которую я прочитал, за исключением видео, говорится, что мне нужно сделать это [EBP - что угодно], чтобы получить значение выше EBP. Спасибо. Теперь все ясно. : D - person srh snl; 22.05.2013

stack-pointer (базовый указатель) -адрес "растет" вниз по направлению к более низкому адресу в адресном пространстве.
Ваш стек начинается, например, с 0x70000000, и когда вы push что-то на нем, esp (ebp) будет понижено на двойное слово -> 0x6ffffffc (если я прав).

См. здесь, здесь и здесь.

person bash.d    schedule 22.05.2013