0

我正在尝试和 Marie 做一个简单的乘法运算来做 (a * b) * (c * d)。我可以通过为每个乘法步骤创建一个新的子程序来做到这一点,但我想尝试使用 JnS 来只使用一个子程序。这是我的代码块

Clear
Store result
Input
Output
Store a
Load a
Skipcond 800
Jump negres
Input
Output
Store b
Load b
Skipcond 800
Jump negres
Input
Output
Store c
Load c
Skipcond 800
Jump negres
Input
Output
Store d
Load d
Skipcond 800
Jump negres
Load a
Store X
Load b
Store Y
JnS loop
Load zoop
Store X
Load zoop
Store Y
Load result
Store Y
Load c
Store X
JnS loop
Load zoop
Store X
Load zoop
Store Y
Load result
Store Y
Load d
Store X
JnS loop
Jump halt


loop,        Load zoop
         Load result
         Add Y
         Store result
         Load X
         Subt one
         Store X
         Skipcond 400
         Jump loop
         Load zoop
         JumpI loop


negres,      Load zoop
         Store result
         Jump halt

halt,   Load result
         Output
         Halt

a, DEC 0
b, DEC 0
c, DEC 0
d, DEC 0
zoop, DEC 0
X, DEC 0
Y, DEC 0
one, DEC 1
result, DEC 0

问题在于我第一次调用循环时,它经历了第一次迭代,传递了 Skipcond 然后从子例程跳回到调用它之后的指令。

这是我第一次使用 JnS,所以任何帮助都会非常感激!

4

1 回答 1

1

JnS指令将返回地址存储在子程序的第一个字中。

(这种方法在 1960 年代很常见,当时处理器的标准是递归调用堆栈——由专用硬件支持,比如有一个堆栈指针。PDP-8 执行子例程调用的方式与 MARIE 完全相同。参数也是内联传递的,例如,作为参数的数据值被立即放置在调用之后(在 PDP-8 上JMS),并且子程序会将返回地址提前超过参数。)

因此,MARIE 子程序需要以一个数据字开始,并且注意这个数据字没有被执行,而是被覆盖。

          ...
          JnS subr         # call subr, maybe from main
          ...
          Halt


subr,     Hex 0            # placeholder for return address
          load Result      # first instruction of subr
          ...
          JumpI subr       # set program counter = return address

此外,因为任何子程序的第一个字是数据(要返回的代码地址),如果你想在函数顶部有一个循环,你需要第二个标签——在第一条代码指令处,即在数据字之后。  Jump subr无法进行循环,因为在 subr 执行数据字会很糟糕,因为它不是指令。

subr,     Hex 0            # placeholder for return address
top,      load Result      # first instruction of subr
          ...
          SkipCond 400
          Jump top         # loop to first instruction of subr
          ...
          JumpI subr       # set program counter = return address
于 2020-11-10T17:34:46.983 回答