-2

Is the return address (the one saved on the stack for the EIP register to use upon returning) the address of the next instruction after call, or is it the instruction address of call?

EDIT:

p call x
q mov y

Is the return address on the stack when calling x() p or q?

user997112
  • 29,025
  • 43
  • 182
  • 361
  • 2
    It's the instruction after the `call`, where the `ret` should return to. Next time consult the instruction set reference. – Jester Mar 13 '14 at 02:23
  • See this stack overflow post: http://stackoverflow.com/questions/17514774/how-do-called-functions-return-to-their-caller-after-being-called – J-Dizzle Mar 13 '14 at 07:24

3 Answers3

1

That after the call - that will be the next instruction executed when the subroutine terminates.

Magoo
  • 77,302
  • 8
  • 62
  • 84
1

The processor pushes the value of the EIP register (which contains the offset of the instruction following the CALL instruction) onto the stack (for use later as a return-instruction pointer).

As @Jester posted, RTFM.

Richard Schneider
  • 34,944
  • 9
  • 57
  • 73
  • Considering I didn't even know there was a "manual" (assuming I found it) reading it would be a little difficult.... – user997112 Mar 13 '14 at 02:39
  • 1
    Richard may be grumpy, but there is literally tons of material out there on these concepts. A more verbose way to rephrase his snark comment is "if you write SW where low-level details are important, pause right there and become best friends with your CPU's instruction set reference". Note this behavior is dictated by the CPU architecture, and not the compiler! – J-Dizzle Mar 13 '14 at 07:28
  • Page 3 of this random google is useful http://mai.kvk.uni-obuda.hu/documents/tantargy/8086-instruction-set-overview.pdf. Pay attention to PUSH, POP, CALL, RET and IRET – J-Dizzle Mar 13 '14 at 07:31
0

The call instruction pushes the return address - in the way you've "numbered" your lines that'd be q - on the stack before transferring execution to the called function.

The ret instruction pops it off - you could say it does pop EIP.
But this also means ... before ret, [ ESP ] == EIP. Since ret does nothing else to the stack but adjust the stackpointer (i.e. ESP -> ESP + 4), by the time you return, you should still have EIP == [ ESP - 4 ].

You could therefore do:

call func
mov EAX, [ ESP - 4 ]

and are very likely to get the code location for the first byte of that MOV instruction.

Why only very likely ? The answer to that is that stack contents within the unallocated parts of the stack aren't guaranteed; there are asynchronous events (UN*X signals and similar mechanisms in other operating systems) which might interrupt execution just between the ret having done the stack pointer adjustment / EIP change but before that instruction actually executes. If that happens, the signal frame might overwrite the unallocated part of the stack, and thereby clobber the return address that was stored there.

If you want to reliably retrieve your current EIP, do a PC-relative call that just "skips the call instruction". Then pop the value on the stack off. I.e. like:

call +5   ;; the size of a call is 5 bytes, so ... "skip yourself"
pop EAX   ;; EAX now contains the "return address" - its own EIP

See also Reading Program Counter directly as previously answered on SO.

Community
  • 1
  • 1
FrankH.
  • 17,675
  • 3
  • 44
  • 63