【发布时间】:2016-12-11 23:52:49
【问题描述】:
我正在尝试用一种类似 ASM 且没有过程的简化语言来实现函数和递归。只有简单的 jumpz、jump、push、pop、add、mul 类型的命令。
命令如下:
(所有变量和文字都是整数)
- set(设置已存在变量的值或声明并初始化新变量)例如(设置 x 3)
- push(将一个值推入堆栈。可以是变量或整数),例如(按 3)或(按 x)
- pop(将堆栈弹出到变量中)例如(pop x)
- add(将第二个参数添加到第一个参数)例如(加 x 1) 或 (加 x y)
- mul(与 add 相同,但用于乘法)
- 跳转(跳转到特定的代码行)例如(jump 3) 将跳转到第 3 行或 (jump x) 将跳转到等于 x 值的 # 行
- jumpz(如果第二个参数等于 0,则跳转到行号)例如(jumpz 3 x) 或 (jumpz z x)
变量“IP”是程序计数器,等于当前正在执行的代码行的行号。
在这种语言中,函数是程序底部的代码块,通过从堆栈中弹出一个值并跳转到该值来终止。 (使用堆栈作为调用堆栈)然后可以在程序中的任何其他位置调用函数,只需将指令指针压入堆栈,然后跳转到函数的开头。
这适用于非递归函数。
如何修改它来处理递归?
我读过用堆栈实现递归是将参数和局部变量压入堆栈的问题(在这种较低级别的情况下,我认为也是指令指针)
我将无法执行 x = f(n) 之类的操作。为此,我需要一些变量 y(也用于 f 的主体),将 y 设置为 n,调用 f 将其“返回值”分配给 y,然后将控制跳转回调用 f 的位置,然后我们将 x 设置为等于 y。
(对定义从第 36 行开始的数字求平方的函数)
1 - set y 3
2 - set returnLine IP
3 - add returnLine 2
4 - push returnLine
5 - jump 36
6 - set x y
...
36 - mul y 2
37 - pop returnLine
38 - jump returnLine
这似乎不适合递归。参数和中间值需要放在堆栈上,我认为堆栈上相同地址的多个实例将由递归调用产生,这很好。
【问题讨论】:
-
好的,我放一个示例程序
-
是的,从第 36 行到第 38 行的块基本上是 f
-
但理想情况下我希望能够做类似递归阶乘的事情
-
比较都必须使用 jumpz 命令完成
-
现在正在学习 :)
标签: recursion assembly callstack