2010-03-30 4 views
7

Это то, что я вижу по демонтируют для утверждения function(1,2,3);:Как адрес возврата указан в стеке?

movl $0x3,0x8(%esp) 
movl $0x2,0x4(%esp) 
movl $0x1,(%esp) 
call 0x4012d0 <_Z8functioniii> 

Похоже адрес RET не выталкивается в стек вообще, то как же ret работу?

ответ

3

Это зависит от ABI и архитектуры, но если обратный адрес заканчивается в стеке, это побочный эффект команды call, которая помещает ее туда.

5

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

+1

Как 'call' сделка с ним тогда? Я просто хочу, чтобы увидеть, где * в отставке адрес * является указанному – Mask

+0

. Вы должны разбить метод вызова на дополнительный шестнадцатеричный код. Об этом будет сказано в чит-листе для набора инструкций, заданных для конкретного процессора. Например, если вы возьмете простейший из микропроцессоров 8085, а инструкция ADD X не покажет второе значение (допустим Y, как ADD X, Y). Вместо этого он добавит значение X к некоторому зарезервированному регистру в процессоре, скажем H, и сохранит значение в H. Бит переполнения должен быть сохранен в другом регистре. Именно так разработана инструкция ADD. Команда CALL также будет иметь аналогичные предопределенные правила. – bragboy

+5

Часть задания команды вызова заключается в том, чтобы направить адрес возврата в стек. Обратный адрес - это адрес непосредственно после параметров для команды вызова. Чтобы узнать, какой адрес возврата находится в вашем примере выше, вам нужно будет посмотреть на стек, как только программа войдет в процедуру на 0x4012d0. –

4

На процессоре x86 (как и в примере с языком сборки) команда call выталкивает адрес возврата в стек и передает управление функции.

Не все архитектуры процессоров помещают обратный адрес в стек - часто есть набор из одного или нескольких регистров, предназначенных для хранения обратных адресов. В процессорах ARM команда BL помещает адрес возврата в конкретный регистр (LR или «регистр ссылок») и передает управление функции. Процессор ia64 делает что-то подобное, за исключением того, что существует несколько возможных регистров (b0 - b7), которые могут принимать обратный адрес, и один будет указан в инструкции (с b0 по умолчанию).

1

вызов помещает текущее значение регистра RIP (обратный адрес) в стек + делает вызов
RET выталкивает обратный адрес (то вызова толкаемых) от верхней части стеки (RSP там регистрируются регистры) и записывает их в регистр RIP.

Пример в ящике GNU/Linux: функция f вызывает функцию g и позволяет посмотреть на фрейм g.

НИЗКИЙ АДРЕС

... < - RSP (указатель стека показывает вершину стека) регистр точек по этому адресу
местные вары г в
указатель базы F 'S (старое значение ОДП) < - ОДП (указатель базы) регистрирует точки по этому адресу
адрес в отставке F 'S (старое значение RIP) (это то, что вызов (от е) толкнул, и что RET (от г) выскочит)
утверждает, что f называется g с и не вписывается в регистры (я думаю, что в Windows это другое)
...

ВЫСОКОГО АДРЕС

г освободит местный ВАР (MOVQ% РСП,% РСБ)
г выскочит «старый ОПБ» и хранить его в ОДПЕ регистре (поп% РСБ)
г будет RET, который изменит RIP со значением, которое хранится где RSP указует на

Надеется, что это помогает

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