nandgame中的Call(函数调用)

本文详细解释了函数调用的过程,包括参数传递、局部存储管理以及调用约定,特别强调了共享内存插槽如ARGS、LOCALS和RETVAL的作用,以及C语言如何通过汇编代码实现这些操作。
摘要由CSDN通过智能技术生成

题目说明:

调用

调用宏用于调用函数。它应该准备好调用的堆栈,
跳转到给定的函数标签,然后在调用后恢复状态。

在调用之前,可能会将零个或多个值放置在堆栈上。
占位符参数计数是参数的数量。

调用约定需要三个共享内存插槽:

ARGS = 1
当前函数参数的地址
LOCALS = 2
函数的本地存储地址
RETVAL = 6
从函数返回的临时值的插槽。
(这些插槽地址可以定义为共享常量以方便使用。)

步骤:

将ARGS的当前值推送到堆栈上
推送LOCALS的当前值。
推送跳转后的地址(返回地址)。
计算一个新的ARGS地址,即当前SP减去参数计数减去3
(因为我们刚刚将三个值推送到堆栈上)。
跳转到由functionName占位符给出的地址。
执行函数调用后,控制将返回到跳转后的标签。

将当前ARGS值存储在临时插槽中。
从堆栈中恢复LOCALS值
从堆栈中恢复ARGS值
将SP设置为先前的ARGS值
将RETVAL推送到堆栈上

level help:

函数可能是软件中最重要的抽象之一。

函数是一段代码单元,接受一些输入(称为参数),
具有用于处理的一些本地存储,并返回一个值。

函数可以从程序中的任何位置执行(调用)。
当调用函数时,调用的地址被存储在堆栈上,
当函数完成时,它返回到调用它的地址。

参数和本地存储也存储在堆栈上。

函数需要三个部分共同工作:

Call:从程序的某处调用函数。
Function:函数的起始点
Return:函数的结束点。
这三个单元需要根据一个共享约定一起工作,
用于确定数据如何进出函数。

代码和注释:
相对于参考代码,加了前面的5个DEFINE

DEFINE ARGS 1
DEFINE LOCALS 2
DEFINE RETVAL 6
DEFINE SP 0
DEFINE TEMP 3
PUSH_STATIC ARGS    //将ARGS的当前值推送到堆栈上
PUSH_STATIC LOCALS  //推送LOCALS的当前值
PUSH_VALUE RETADDR  //推送跳转后的地址(返回地址)
A = SP
D = *A
A = 3               //栈内放了3个值
D = D - A           //栈顶减3
A = argumentCount   //参数个数
D = D - A
A = ARGS
*A = D
GOTO functionName  //跳转到由functionName占位符给出的地址
RETADDR:           //执行函数调用后,控制将返回到跳转后的标签
A = ARGS
D = *A
A = TEMP
*A = D             //将当前ARGS值存储在临时插槽中
POP_STATIC LOCALS  //从堆栈中恢复LOCALS值
POP_STATIC ARGS    //从堆栈中恢复ARGS值
A = TEMP
D = *A
A = SP              //将SP设置为先前的ARGS值
*A = D
PUSH_STATIC RETVAL  //将RETVAL推送到堆栈上

实际通过gcc、vc之类的编译器可以得到c语言的汇编代码

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值