Instructions
x86-64CALL / RET
CALL pushes the return address and transfers control; RET pops it and jumps back — the backbone of the x86-64 call stack.
CALL and RET implement the x86 subroutine mechanism. Together they maintain
the return-address chain that makes nested function calls possible.
Operation
call target ; PUSH RIP (next instruction) ; JMP target
ret ; POP RIP (jump to return address)
ret 0x10 ; POP RIP ; RSP += 0x10 (stdcall stack cleanup)CALL is effectively push rip; jmp target. The pushed value is the address
of the instruction immediately after the call.
RET pops the top of the stack into RIP, resuming execution at the return
address. A ret N (far or near with immediate) additionally releases N bytes
of stack — used by the Microsoft __stdcall convention.
Call forms
| Form | Example | Notes |
|---|---|---|
| Direct near | call 0x401234 | Relative 32-bit displacement |
| Indirect via register | call rax | Virtual dispatch, callbacks |
| Indirect via memory | call [rax] | vtable lookup: call [rax+0x18] |
Reverse-engineering notes
- vtable calls appear as
call [rax]orcall [rax + offset]; the pointer in memory is the method address. IDA/Ghidra usually resolve these if the type is known. call $+5; pop raxis a classic PIC/shellcode trick to get the currentRIPvalue into a register (the call pushes the next instruction's address).- A
retthat jumps to an unexpected address is the heart of ROP (Return-Oriented Programming) exploitation. - When a tail call optimisation is applied, the compiler replaces
call f; retwith justjmp f— so the absence ofretat the end of a function does not always mean a non-returning function.