Normally when I write assembly for a 8051 chip. I use the registers R0-R7 for arguement before I call functions.
mov r6, #6
mov r7, #2
lcall setpos
I was interested in doing this with using the stack (ignoring the fact that this may be less efficient). Searching on the internet I found an awnser in this link
I was missing something in the answer. In the answer he does the following
push #0
push #5
call function
pop r7 ; return value -> r7
...
function:
pop r7
pop r6 ; store return address
pop b ; 5 -> b
pop a ; 0 -> a
add a, b
push a ; store result in a and push it
push r6
push r7
ret
I thought that every register was modify-able including the stack pointer so it is possible to do
push #4
push #8
call function
pop r7 ; result -> r7
...
function:
dec SP ; leave return address untouched
dec SP
pop r4 ; 8 -> A
pop r5 ; 4 -> B
add A, B
inc SP
push A; push result
ret
instead? And am I doing it correctly?
Your idea is not that bad since it does not need registers to buffer the return address, uses less clock cycles, and uses less code space.
There is only one issue to be aware of: Because the return address keeps its place in the stack also all space for the arguments is in use. At the calling site you have to POP <any>
or DEC SP
the same amount as was pushed before the call.
So your example should be:
push #4
push #8
call function
pop r7 ; result -> r7
dec sp
The called function must not change the SP before returning:
function:
dec SP ; leave return address untouched
dec SP
pop r4 ; 8 -> A
pop r5 ; 4 -> B
add A, B
inc SP
push A; push result
inc SP
inc SP
ret
Additional note: PUSH
and POP
only take an address of the internal RAM (00H to 7FH) and special function registers (80H to 0FFH) as parameter. There are no variants for immediate values. Even if you write PUSH R2
the absolute address of R2 in the current register set is used.