本文承接上一篇博文,继续介绍使用hack computer的指令(下文简称指令)实现sum 10的汇编程序。
完整程序如下,基本完整参考了1中的例子。
// Adds 1+...+10
@i
M=1
@sum
M=0
(LOOP)
@i
D=M
@10
D=D-A
@END
D;JGT
@i
D=M
@sum
M=D+M
@i
M=M+1
@LOOP
0;JMP
(END)
@END
0;JMP
整个程序结构很清晰,分为3个部分:初始化变量、循环做加法和以无限循环作为结束。
在分析具体指令代码之前,先来看一段程序动态运行状态:
下面分析具体程序指令代码。
1.初始化变量
这里初始化了2个变量:i
和sum
,我们知道变量是存放在内存里,所以这里学习指令代码如何在内存中声明一个变量,并做初始化。
首先用到了@
指令,前文已经介绍过,@value
叫做A-Instruction
(A指令),赋值A寄存器的值为value
,value可以是一个非负数的十进制数或者symbol(该symbol refer这样类型的数)。
接下来是一个新的指令,M
指令,给内存赋值,实际意义相当于M[A]
。
The Hack ALU is designed to compute a fixed set of functions on the D, A, and M registers (where M stands for Memory[A]).
我们知道,CPU在对内存进行操作的时候,首要知道内存地址,而CPU是和寄存器直接交互的,所以地址肯定要先存放在某个寄存器里。而hack computer指令的设计是使用A寄存器,所以,M=1实际上是M[A]=1
,把A寄存器的值作为内存地址,并赋为1。
理解了这2条指令,再来看初始化代码就很清晰了:
@i
M=1
@sum
M=0
- 声明变量
i
:把A寄存器的值赋值为i,然后使用M指令,把内存M[i]的值初始化为1; - 声明变量
sum
:把A寄存器的值赋值为sum,然后使用M指令,把内存M[sum]的值初始化为0。
相当于高级语言:
i=1;
sum=0;
但这里有个问题,i
和sum
都是symbol,按照要求必须refer一个非负的十进制数,但是在代码中并没有初始化symbol本身的代码?
实际情况是,在汇编代码被编译为hack computer byte-code(字节码)的时候(该过程在把汇编程序载入CPU模拟器时自动发生),编译器会为自动的为symbol i和sum替换为一个非负的十进制数。也就是在实际运行的字节码中,是没有symbol这个概念的,例如当这段汇编代码被载入模拟器:
i
被替换为了16,sum
被替换为17,而在前4条指令执行完毕以后,内存地址16(变量i)的值为1,内存地址17(变量sum)的值为0。
2.循环做加法
如果使用高级语言,那这里代码逻辑相当于:
for(;i<=10;i++) {
sum += i;
}
下面看使用hack computer的汇编代码如何实现以上逻辑。
(LOOP)
@i
D=M
@10
D=D-A
@END
D;JGT
@i
D=M
@sum
M=D+M
@i
M=M+1
@LOOP
0;JMP
- 首先还是
@i
指令,把A寄存器的值赋值为i,这里是16 - 接下来
D=M
,即是D=M[16]
,把内存地址16的值赋值给D
寄存器,相当于D=i
。执行完该条指令之后,D寄存器的值为1 @10
把A寄存器的值赋值为10,10是循环条件了。D=D-A
:此时D的值为1,A为10,ALU
对D和A寄存器进行减法运算,执行完该条指令后D为-9,如下图
执行指令之前:
执行指令之后:
@END
:设置A寄存器的值为END(被编译器替换为18),为下一条的跳转指令做准备D;JGT
:判断D寄存器值是否大于0,如果是则跳转到END的地址执行,相当于设置跳出循环的条件,这里由于D寄存器(-9)小于0,不执行跳转。@i
和D=M
:和1、2条指令类似,把内存16的值赋值给D,执行完之后D值为1@sum
和M=D+M
:取出sum(内存地址17的值,此时为0),与D相加(这里相当于执行sum的第1次加法了,加1),结果再放入内存地址17中,此时值改变为1,如下图
@i
和M=M+1
:取i的值,并+1,相当于i++
@LOOP
:设置A寄存器为LOOP(被编译器替换为4),为下一条跳转指令做准备0;JMP
:无条件跳转到LOOP位置,即PC counter为4的指令开始执行,准备开始下一轮循环,如下图
这样就完成了第1次的循环,这样的循环一共要进行10轮,最后完成sum10。
3.程序结束
10轮循环完成后,此时sum值(内存地址17)为55,i
值(内存地址16)应为11。继续执行到第7条指令D=D-A
,D为11,A为10,所以执行完毕后D=1。然后第9条指令跳转指令,因为D>0,发生跳转到END位置(即第18条指令),进入无限循环作为结束,无限循环在前文已经介绍过。