管理参数和 return 地址时处理堆栈的正确约定
Proper convention for handling the stack when managing parameters and the return address
当您需要访问参数 'below' 在堆?我使用的是 S12 Motorola/Freescale 处理器。 (S12有:16位的D寄存器由A和B寄存器组成,每个寄存器有8位。X和Y索引寄存器各16位,一个程序计数器和一个堆栈指针)代码示例是:
MAIN ORG 00 ;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(这看起来很老套)或者我将不得不拉出堆栈的顶部并将其存储在一个寄存器中向上 space。最后一种方法的一个转折是将 return 地址存储在一个变量中,不幸的是,这里声明的变量是全局范围的,这感觉并不理想。
ReturnAddress EQU 00 ;Declare variable at address 00
STD ReturnAddress ;Store the D register's contents in variable
是否还有我在这里没有看到的其他选项?
感谢 Jester 的一些输入,观察堆栈中发生的事情并使用其中包含的参数是相当简单的。我写了一个简单的程序来演示按值和引用传递参数。
QUOTIENT EQU 00 ;Variable to hold our QUOTIENT
REMAINDER EQU 02 ;Variable to hold our REMAINDER
MAIN ORG 00 ;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 [=10=]A, 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
当您需要访问参数 'below' 在堆?我使用的是 S12 Motorola/Freescale 处理器。 (S12有:16位的D寄存器由A和B寄存器组成,每个寄存器有8位。X和Y索引寄存器各16位,一个程序计数器和一个堆栈指针)代码示例是:
MAIN ORG 00 ;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(这看起来很老套)或者我将不得不拉出堆栈的顶部并将其存储在一个寄存器中向上 space。最后一种方法的一个转折是将 return 地址存储在一个变量中,不幸的是,这里声明的变量是全局范围的,这感觉并不理想。
ReturnAddress EQU 00 ;Declare variable at address 00
STD ReturnAddress ;Store the D register's contents in variable
是否还有我在这里没有看到的其他选项?
感谢 Jester 的一些输入,观察堆栈中发生的事情并使用其中包含的参数是相当简单的。我写了一个简单的程序来演示按值和引用传递参数。
QUOTIENT EQU 00 ;Variable to hold our QUOTIENT
REMAINDER EQU 02 ;Variable to hold our REMAINDER
MAIN ORG 00 ;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 [=10=]A, 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