管理参数和返回地址时处理堆栈的适当约定



当您需要访问堆栈中位于调用函数"下方"的参数时,处理将调用函数的返回地址放在堆栈中任何参数之上的最佳方法是什么?我使用的是S12摩托罗拉/Freescale处理器。(S12有:D寄存器,16位,由A和B寄存器组成,每个寄存器有8位。X和Y索引寄存器,每个寄存器16位,一个程序计数器和一个堆栈指针)代码示例为:

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

问题是堆栈的顶部保存着下一条指令的地址,这使得它很难操作。例如,如果我需要一个位于地址下方的参数,我将不得不手动调整SP(这似乎很麻烦),或者我将不得不拔下堆栈的顶部并将其存储在占用空间的寄存器中。最后一种方法的一个转折点是将返回地址存储在变量中,不幸的是,这里声明的变量在范围上是全局的,这感觉并不理想。

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

还有其他我没有看到的选择吗?

由于Jester的一些输入,能够观察堆栈中发生的事情并使用其中包含的参数非常简单。我编写了一个简单的程序,演示通过值和引用传递参数。

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

最新更新