0

I know that the call / ret is something that is done internally, but I wanted to understand a bit more about how it might be translated in assembly code. Here is what I have so far for call:

# Verbose way of doing `call func`

lea (%rip), %rax   # get the current %rip. It cannot be directly accessed, so need to do a roundabout way
add $14, %rax      # now that we have the previous %rip address in a register, add the offset to after the jmp
sub $8, %rsp       # do pop %rax to move the value in the register onto the stack
mov %rax, (%rsp)   #    ... (doing it verbosely)
jmp func           # jump to the function label

And for ret:

 func:
     nop                 # pretend we did something in the function

     # Verbose way of returning from a function, `ret`
     mov (%rsp), %r11    # move the memory address stored at the top of the stack into %r11
     add $8, %rsp        # move the stack pointer back to where we started from
     jmp %r11            # jump to the return address, now held in %r11

Is this more-or-less what call / ret does?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
samuelbrody1249
  • 4,379
  • 1
  • 15
  • 58
  • 2
    Yes. As I commented under your other question, ignoring changed registers and flags. Also assuming your `14` is the correct offset. You might want to just use a label instead. – Jester Aug 29 '20 at 23:49
  • 1
    You could simplify to `lea after_jmp(%rip), %rax` to calculate the return address directly with a RIP-relative addressing mode. But of course for a single `call` instruction, the return address is already available as RIP+0; every instruction effectively knows its end. – Peter Cordes Aug 30 '20 at 02:11
  • Also, near exact duplicate of [Writing a function call (call / ret) in long-form](https://stackoverflow.com/q/63642416) asked only yesterday. – Peter Cordes Aug 30 '20 at 02:13

0 Answers0