Proper convention for handling the stack when managing parameters and the return address

130 Views Asked by At

What is the best way to handle having the return address of a calling function on top of any parameters that have been placed in the stack when you need to access parameters 'below' it in the stack? I am using the S12 Motorola/Freescale processor. (The S12 has: D register with 16 bits consisting of A and B registers each of which has 8 bits. X and Y index registers each 16 bits, a program counter and a stack pointer) A sample of the code is:

MAIN ORG    $1500        ;Set the start of the program 
     LDD    #SomeValue   ;Load the D register with a value
     PSHD                ;Push D onto the stack
     JSR    ROUTINE      ;Go to the subroutine - pushes the PC to the SP
END_MAIN    END

ROUTINE     
     PULD                ;Pull the top of the stack into the D register
                         ;D now holds the address for returning to the 
                         ;main function. 
     PSHD                ;Push the return address back onto the stack
END_ROUTINE RTS          ;Return to Main routine

The problem is that the top of the stack holds the address for the next instruction which makes it difficult to maneuver around. For example, if I needed a parameter that is underneath the the address, I would have to either manually adjust the SP (which seems rather hacky) or I will have to pull the top of the stack off and store it in a register which takes up space. A twist on the last approach is to store the return address in a variable, unfortunately, the variables declared here are global in scope, which does not feel ideal.

ReturnAddress EQU $2000        ;Declare variable at address $2000
STD           ReturnAddress    ;Store the D register's contents in variable

Is there another option which I am not seeing here?

1

There are 1 best solutions below

2
acampb311 On BEST ANSWER

Thanks to some input from Jester, it is fairly simple to be able to observe what is happening in the stack and to use parameters contained therein. I wrote a simple program that demonstrates passing parameters by value and reference.

QUOTIENT    EQU     $1000       ;Variable to hold our QUOTIENT
REMAINDER   EQU     $1002       ;Variable to hold our REMAINDER

MAIN        ORG     $2000       ;Set the start of the program
            LDD     #!50        ;Load the D register with a value (16 bits)
            PSHD                ;Push D onto the stack (16 bits)
            LDD     #!10        ;Load the D register with a value (16 bits)
            PSHD                ;Push D onto the stack (16 bits)
            LDD     #QUOTIENT   ;Load the D register with an address (16 bits)
            PSHD                ;Push D onto the stack (16 bits)
            LDD     #REMAINDER  ;Load the D register with an address (16 bits)
            PSHD                ;Push D onto the stack (16 bits)
            JSR     DIVIDE      ;Push the PC onto the stack (16 bits).
            LEAS $0A, SP         ;Instead of PULD 5x, thanks Jester
END_MAIN    END


;******************************************************************************;
;DIVIDE - This routine expects the following parameters to be on the stack:
; STACK
;( 0 ) - (16 bits for return address)
;( 2 ) - (16 bits of address to store the REMAINDER (ANSWER var reference))
;( 4 ) - (16 bits of address to store the QUOTIENT (ANSWER var reference))
;( 6 ) - (16 bits for divisor)
;( 8 ) - (16 bits for dividend)
;******************************************************************************;
DIVIDE      LDD     8,SP       ;Loads the dividend (50)
            LDX     6,SP       ;Loads the divisor (10)
            IDIV               ;Divide
            LDY     4,SP       ;Get the address of the Quotient
            STX     0,Y        ;Store at that address
            LDY     2,SP       ;Get the address of the remainder
            STD     0,Y        ;Store at that address
END_DIVIDE  RTS