Инструкция Retq, куда она возвращается

Я не могу понять, куда возвращается инструкция по сборке retq.

Я понимаю, что когда мой обычный код выполняется, он возвращается на адрес, указанный в стеке. Но как он узнает, где в стеке находится адрес возврата?

Короче говоря, использует ли он rbp или esp для поиска адреса в стеке?


person Kaushal Shah    schedule 19.08.2013    source источник
comment
Если вы хотите поэкспериментировать, попробуйте заменить retq на addq $8, %rsp; jmpq -8(%rsp). Функционально эквивалентен (хотя и не с точки зрения производительности).   -  person FrankH.    schedule 11.09.2013


Ответы (2)


После изучения ассемблерного кода вот мои мысли, давайте посмотрим на пример:

fun:
push %rbp
mov %rsp,%rbp
...
...
pop %rbp
retq

main:
...
...
callq  "address" <fun>
...
...

Мы видим, что перед retq есть инструкция. Инструкция pop %rbp (иногда это инструкция выхода, но они похожи)

  1. сохранить содержимое текущего указателя стека %rsp в указатель базового стека %rbp.
  2. переместите указатель %rsp на предыдущий адрес в стеке.

Например: перед командой pop %rsp указывало на 0x0000 0000 0000 00D0. После команды pop он указывает на 0x0000 0000 0000 00D8 (предположим, что стек растет от старшего адреса к младшему).

После команды pop теперь %rsp указывает на новый адрес, а retq принимает этот адрес в качестве адреса возврата.

person cppython    schedule 05.09.2013

ret - это то, как вы пишете pop rip на x86: всплывающее окно стека и непрямая ветвь к этому значению. https://www.felixcloutier.com/x86/ret точно документирует, что он делает и чего не делает. не делать.

Фактически это pop %tmp / jmp *%tmp, где tmp — внутренний временный регистр.

ret зависит только от RSP.

Использование RBP в качестве указателя фрейма является совершенно необязательным программным соглашением, которое современные компиляторы не используют даже при включенной оптимизации.

person Peter Cordes    schedule 10.10.2019