When you pass parameters to a function on the cpu stack,
You put the parameters on then JSR puts the return address on the stack. So that means in your function you must take the top item of the stack (the return address) before you can take the others off)
The return value is stored by convention in register D0
.
eg is the following the correct way to go about it:
...
|Let’s do some addition with a function,
MOVE.L #4, -(SP)
MOVE.L #5, -(SP)
JSR add
|the result of the addition (4+5) is in D0 (9)
...
add:
MOVE.L (SP)+, A1 |store the return address
|in a register
MOVE.L (SP)+, D0 |get 1st parameter, put in D0
MOVE.L (SP)+, D2 |get 2nd parameter, put in D2
ADD.L D2, D0 |add them,
|storing the result in D0
MOVE.L A1, -(SP) |put the address back on the
|Stack
RTS |return
You do not "take off" parameters from the stack, in the sense that you don't pop them. You usually assign a frame register to point to the top of the stack at the entry point to the procedure, and access the parameters at constant, known offsets from the frame pointer. Then your index just "skips" the return address, which you know is there.
E.g. in some hypothetical assembly, when you're in a procedure. Suppose stack is growing down:
...
argument2
argument1
ret addr <---- stack pointer
So just access argument1
at offset sp+4
(assuming 32-bit), argument2
at offset sp+8
, etc. Since these calling conventions are known, these offsets are hard-coded in your code and are efficient to compute.
The frame pointer is very useful since you also push the local variables to stack, and you wouldn't want indexing of parameters to change in different places, so the frame pointer provides a stable anchor throughout the execution of the procedure.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With