在管理参数和返回地址时处理堆栈的正确约定

第311章

当您需要访问堆栈中“在其下方”的参数时,处理调用函数的返回地址位于已放置在堆栈中的任何参数之上的最佳方法是什么?我正在使用S12 Motorola / Freescale处理器。(S12具有:由A和B寄存器组成的16位D寄存器,每个寄存器具有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(看起来很hacky),或者必须拉开堆栈的顶部并将其存储在一个寄存器中,该寄存器需要空间。最后一种方法的一个变种是将返回地址存储在变量中,不幸的是,此处声明的变量在范围上是全局的,这并不理想。

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

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

第311章

得益于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

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

x64 参数和返回值调用约定

如何正确管理内存堆栈和视图控制器?

窗口管理器动画状态和活动返回堆栈

在AWS中创建堆栈时处理动态参数值

.NET 中的调用约定和堆栈遍历

了解调用约定和堆栈指针

函数调用返回时,压入堆栈的参数会怎样?

汇编x86-返回地址被压入堆栈后,堆栈指针如何保持局部变量的正确位置?

在CDECL调用约定中,可以重用推入堆栈的参数吗?

如何在处理和粘贴时使单元地址不变?

函数堆栈是否保存返回地址?

堆栈上的线程返回地址是什么?

堆栈变量的C返回地址= NULL?

使用其他函数的返回值作为参数调用函数时是否使用了调用堆栈和执行上下文?

处理其他异常时,如何获取正确链接的堆栈跟踪以查找引发的异常?

在 Python 中实现 peek() 方法时处理空堆栈的正确方法

返回类实例时的Numpydoc样式约定

C# 封送处理、ubalanced 堆栈和正确获取 PInvoke 签名

Dapper 和 list 参数在 ',' 附近返回不正确的语法

调用传递多个参数的函数时,处理被调用者进入堆栈的寄存器

iOS-返回时如何推送到视图控制器并维护正确的“视图堆栈”

返回地址预测堆栈缓冲区与堆栈存储的返回地址?

片段返回堆栈和isRemoving()

在 ARM macOS 上,当显式 raise()-ing 信号时,堆栈上的某些返回地址会出现乱码

当客户端和服务器在不同的机器上时,getsockname() 不会返回正确的地址

ASIO处理程序参数和boost :: bind,编译时错误

为什么在多线程处理时Rcout和Rprintf导致堆栈限制错误?

在Swift中也管理ifaddrs以返回MAC地址

返回通过参数的堆栈导航器?