address | item | comment |
---|---|---|
high | \(\mathrm{arg}_{n-1}\) | optional, caller pushes |
\(\mathrm{arg}_{0}\) | optional, optional, caller pushes | |
return address | mandatory, caller pushes, the SP points here at entry point of the callee | |
last local variable | optional, allocated by callee | |
low | first local variable | optional, allocated by callee, the SP points here after local var allocation |
This can be reflected using label definitions. Each label defines an offset from where the SP points to after local variables (if any) is allocated:
firstLocalVar: 0
secondLocalVar: firstLocalVar firstLocalVarSize +
// ...
lastLocalVar: secondLastLocalVar secondLastLocalVarSize +
localVarSize: lastLocalVar lastLocalVarSize +
retAddr: localVarSize
arg0: retAddr 1 +
arg1: arg0 arg0Size +
// ...
argLast: argSecondLast argSecondLastSize +
The label localVarSize
is useful for the allocation and
deallocation of local variables. To allocate, decrease the SP by this
amount. To deallocate, increase the SP by this amount.
Keep in mind, however, that TTPASM is a single file. This means these labels should be prefixed by the subroutine to make sure there is no name collision.
Using such label definition, the allocation of local variables at the entry point of a function is uniform:
ldi a,localVarSize
sub d,a
This is matched by the code to deallocate the local variables at the end of the subroutine, just prior to popping the return address.
ldi a,localVarSize
add d,a
In between the allocation and deallocation of the stack space for local variables, local variables can be accessed the same way as parameters.
It can be helpful to recognize patterns of instructions. For example, the following is a push operation:
dec d
ldi a,value
st (d),a
However, it is also important not to be over-specific because the
dec d
instruction can exchange order with the
ldi
instruction in this case. As a result, it is more
helpful to recognize a more general pattern:
// some instructions that do not work with reg D
dec d
// some instructions that do not work with reg D
st (d),a // reg A is just an example, can be any register
Note that in this case, as long as register A is determined prior to
the st (d),a
instruction, and the value of register A does
not depend on the value of register D, register A can be set before or
after the dec d
instruction.