psABI / RV64 stack-frame simulation

RISC-V Two-Argument Function Call with RV64 Stack Frame Demo

Example: caller calls foo(3, 5). Arguments use a0/a1; stack memory shows foo saving ra/s0, restoring them, and freeing a 16-byte-aligned stack frame.

This page uses RV64 instructions and a 32-byte stack frame; real compilers may emit shorter sequences depending on optimization level, frame-pointer use, and leaf-function rules.

Step 1 / 11

caller

focus
1li a0, 3
2li a1, 5
3call foo
4after_call:
5# a0 = 8
PC
caller
a0
3 (arg0)
a1
5 (arg1)
ra
old ra
Stack space
The stack has not moved; sp still points at the caller stack top.
current sp
0x80001000
sp unchanged in this step
no stack data movement in this step
High addressStack grows downward
future frame range: 0x80000fe0-0x80000fff
each row is 8 bytes
blue arrow = current sp
0x80001000boundary
pre-call stack-top boundary
entry spsp
caller stack top
0x80000ff80x80000ff8-0x80000fff
return-address slot
24(sp)
unallocated
0x80000ff00x80000ff0-0x80000ff7
frame-pointer slot
16(sp)
unallocated
0x80000fe80x80000fe8-0x80000fef
local/temp slot
8(sp)
unallocated
0x80000fe00x80000fe0-0x80000fe7
frame-base slot
0(sp)
unallocated

foo

quiet
1foo:
2addi sp, sp, -32
3sd ra, 24(sp)
4sd s0, 16(sp)
5add a0, a0, a1
6ld s0, 16(sp)
7ld ra, 24(sp)
8addi sp, sp, 32
9ret
PC
idle
ra
-
s0/fp
preserved
a0/a1
args
sp
0x80001000
Key notes

Boundaries that often get mixed up

sp

When addi sp is highlighted, this page shows the before-execution state; by the next instruction, sp has moved to the new value.

ra

call writes ra; ret returns through ra. Saving ra is the function's own state preservation, not an automatic push by call.

s0/fp

s0/fp is the callee-saved register shown in this example; real functions save only registers they modify and must preserve by the ABI.

Semantic boundary

This page demonstrates an ordinary function call, not ECALL/trap. A function call does not switch privilege level or write EPC/cause trap state automatically.