выскакивая из стека, не толкнув - PullRequest
3 голосов
/ 24 августа 2011

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

Стек увеличивается, причем регистр ESP всегда указывает на вершину стека ... адрес в низком объеме памяти. Если что-то помещено в стек, ESP следует уменьшить.

EBP используется в качестве указателя кадра и, насколько я понимаю, всегда должен быть больше, чем ESP.

Еще со следующей программой:

stdout.put(esp, nl);
stdout.put(ebp, nl);
push(ike);
stdout.put(esp, nl);
stdout.put(ebp, nl);
push(ike);
stdout.put(esp, nl);
stdout.put(ebp, nl);
pop(eax);
pop(eax);
pop(eax);
pop(eax);
stdout.put(esp, nl);
stdout.put(ebp, nl);

Кажется, это не так. Глядя на вывод:

0018FF6C 0018FF70

0018FF68 0018FF70

0018FF64 0018FF70

0018FF74 0018FF70

EBP всегда одинаков, ESP уменьшается на 4 байта для первого нажатия, затем еще на 4 байта для второго нажатия.

Именно после этого я запутался. После моих первых двух всплывающих окон ESP должен вернуться к тому, с чего все началось. Как я могу сделать еще два всплывающих окна, если я ничего не положил в стек? Что я выскакиваю?

Дальнейшее выталкивание и распечатка из EAX показывает некоторые цифры, а затем 0 и затем дополнительные цифры. Итак, я определенно что-то попсовал ... но что? К какой части памяти моей программы она принадлежит и почему ничего не влияет?

Почему EBP вообще не затрагивается?

Кроме того, почему ESP уменьшается на 4 байта, а не на 8?

Если бы кто-то мог помочь мне понять это, я был бы очень признателен.

Ответы [ 2 ]

1 голос
/ 24 августа 2011

EBP не модифицируется инструкциями push / pop, он настраивается вручную, поэтому, если вы не измените его самостоятельно, он останется прежним.

Приводы IKE приводят к 4-байтовым изменениям,очевидно, что вы находитесь здесь в 32-битном режиме.

4 всплеска EAX (32-бит) приведут к 16-байтовому (10-часовому) изменению, так же, как и они.

Не уверен, что проблема здесь.Кажется, работает так, как я ожидал?

0 голосов
/ 24 августа 2011

Стек используется для хранения, помимо того, что вы нажимаете и выталкиваете, стековый фрейм каждой функции (т.е. локальные переменные), адрес возврата, старый ebp (в частности, где находится текущий ebp) и параметры функции.Итак, что вы выводите, это стековый фрейм вашей функции.
Если вы разберете программу, вы увидите:

push    param3          ; suppose func takes 3 parameters, they're
push    param2          ; pushed in reversed order (C-style)
push    param1
call    func            ; call pushes also the return address, i.e. the
                        ; address of the instrucion after the call

...

func:
push   ebp              ; this is done for preserving the caller's stack frame
mov    ebp, esp         ; now we set up the beginning of func's stack frame
sub    esp, smth.       ; and its width, enough to fit all func's variables

В этот момент стек будет выглядеть примерно так:

        00000058:    arg3
        00000054:    arg2
        00000050:    arg1
        0000004c:    return address
 ebp -> 00000048:    caller's ebp
        ...          ...               -
        00000034:    random stuff       |  func's stack frame, random because they
        00000030:    random stuff       |  are uninitialized
 esp -> 0000002c:    random stuff      - 

Наконец, вы нажимаете и извлекаете только 4 байта за раз, потому что это размер слова вашей машины, таким образом вы можете сохранить целые регистры.в один выстрел

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...