sq(x){ return x * x; }
main(){
a = sq(2);
print(a);
}
This is the output from the RZ compiler
.sHere is the explanation what the code sequence does:
rz 0
retv 28
bp 29
rads 30
sp 31
print 1
printch 2
.a 0
.c
ld sp #1000 ;; sp
ld bp #3000 ;; bp
jal rads label_18
trap stop rz;; Func sq 1 0
:label_5
add bp bp #2
;; -- save regs
st @1 sp r1
st @2 sp r2
add sp sp #2ld r1 @-1 bp ;; x
ld r2 @-1 bp
mul r1 r1 r2
or retv r1 rzsub bp bp #2
;; -- restore regs
ld r1 @-1 sp
ld r2 @0 sp
sub sp sp #2
jr rads;; -- Func main 0 1
:label_18
add bp bp #2
st @0 bp rads
;; ---- save regs
st @1 sp r1
add sp sp #1ld r1 #2
st @1 bp r1
jal rads label_5
or r1 retv rz
st @-1 bp r1 ;; ald r1 @-1 bp
trap print r1ld rads @0 bp
sub bp bp #2
;; -- restore regs
ld r1 @0 sp
sub sp sp #1
jr rads.e
add bp bp #2
the size of the activation record of sq() is 2 words. One word stores return-address, the other word is the local variable x. This function uses two registers: r1, r2, so they are saved in the stack using this sequence:
st @1 sp r1
st @2 sp r2
add sp sp #2
A stack is a data structure, it is accessed by Last-In-First-Out order. It is used as a temporary storage in which one doesn't have to specify the actual location, a value can be saved by "pushing" it to a stack, and a value can be retrieved by "poping" it from a stack.
When the calculation in a function is completed, a return-value is stored in a register, specially assigned for this purpose, r28 in this example.
ld r1 @-1 bp ;; x
ld r2 @-1 bp
mul r1 r1 r2
or retv r1 rz
The above sequence did x * x and the result is in the register "retv" which is r28.
To return from a function call, the activation record is deleted, registers are restored from a stack and the return-address is restored then jump back to the caller using "jr rads". In this example, the return-address in "rads" has not been altered therefore there is no need to save and restore it.
sub bp bp #2
;; -- restore regs
ld r1 @-1 sp
ld r2 @0 sp
sub sp sp #2
jr rads
At the main() function, the code starts similar to sq() (all functions behave in similar ways), by creating its own activation record. The call to sq() passes a value (x) to it. In this case, the value is a constant 2. This value is written into the "future" activation record (which is the AR of sq()) as its first local variable (x) using the offset +1. Then the call is performed by "jal" , the link register is "rads", r30 in this example.
ld r1 #2
st @1 bp r1
jal rads label_5
When the call is returned, the return value is in "retv". At the termination of main(), the control is transferred back to its caller, the return-address is restored from the current AR, the current AR is deleted, registers are restored and jump back to the caller.
ld rads @0 bp
sub bp bp #2
;; -- restore regs
ld r1 @0 sp
sub sp sp #1
jr rads
The first part of the program is the initialisation of the stack pointer and base pointer and then call to main().
ld sp #1000 ;; sp
ld bp #3000 ;; bp
jal rads label_18
trap stop rz
the end.
last update 2 July 2003