首页 > 其他分享 >Nand2tetris Part1 lab04-lab06

Nand2tetris Part1 lab04-lab06

时间:2024-02-04 17:55:19浏览次数:27  
标签:register Image RAM 指令 lab04 lab06 hack Nand2tetris CPU

概述
在前三个 lab 中,我们构建了 hack 计算机所需要的基础的芯片。后三个 lab 则是教我们如何使用这些芯片去搭建一个 hack 计算机并且使用汇编语言。
Week04 & Week05
把这两个 lab 放在一起是因为他们给我的感觉更像是知识的互补。 lab05 教会你汇编语言的规范是什么, lab06 则是如何搭建 CPU, 最后变成一个 hack 计算机,在这其中你会知道为什么汇编语言的规范是这样子的。
关于汇编语言

[Image]
寄存器
要知道汇编语言的逻辑,首先应该从 CPU 本身来看(当然,你现在不需要钻研,因为是下一讲的内容)。容易发现,我们现在有 A register ,D register , 还有一个 inM(M register)。他们的作用分别是:

  • A register : 储存地址,使用 @address 召唤
  • D register: 作为一个 temp 使用
  • M register: 存放的是 A register 这个地址对应的 RAM 值
    注意,在 hack 计算机架构中,RAM 用来存放值, ROM 用来存放指令(你可以在他给的 CPUEmulator 里面看见)
    有了这三个寄存器,我们可以实现几乎所有功能。
    首先回忆你构建的一个不起眼的芯片 PC。就是那个实现了自增/换值的寄存器。他在我们 CPU 架构的最低下。他实现了一个有趣的功能:掌控当前用到第几个 ROM 里面的指令了。也就是说,我们既可以逐步 +1 的读指令,也可以跳转。这就是 jump 的实现(也就是你诸如 循环等东西实现的法则)。
    指令
    在 hack 架构中,我们仅仅只有两种指令:
  • A instruction: 使用 @address 使用,作用就是把 A reg 的值变成你刚刚 @ 了的地址。
  • C instruction: 使用 dest=comp;jump 来实现。 其中,dest 是你的要赋值的对象,comp 是你的ALU 计算式子,jump 是你的跳转规则。这三个的详细要求可以看下面的图或者自行查阅。
    [Image]

值得一提的是你的 aa 那里是有顺序要求的(当你写到 lab06 就知道这个要求的好了)
这些就是组成汇编的核心部分,除此之外,我们还有变量(小写)和标签(大写)的说法
标签:
想象一下你想在你的汇编程序中频繁的使用各种 jump(这很常见),但你的指令读进 ROM 的时候并不是从 0 开始的,这时候,你的跳转(如果直接写地址的话),就很小丑了。所以我们引入了标签这个概念,让代码同时具有通用性和可读性。
使用方法很简单,通过 (LABEL) 来声明,以后直接 @LABEL 就可以正常使用了。(本质上就是一个 map)
变量:
同样的,我们也给 RAM 提供一些辅助,也就是变量。使用的时候直接 @variable 就可以了,如果这个变量还没用过,就会自己去 RAM 里面声明一个空间(通常是按照顺序的)。
顺便一提的是,为了方便使用,这里已经有被定义的值了:
[Image]
我们可以看几个简单的例子
[Image]
同样要注意的是,汇编程序没有一般意义上的终止,他只会遵循 PC 的值一直走下去,所以你如果不在末尾做出一些处理的话,容易刹不住车跑到其他 ROM 区域去。解决方法也很简单,你可以在末尾加个死循环:
[Image]
这样它就会一直停在这里了。
IO
最后是键盘和显示的事情。
关于键盘,在 hack 架构中,RAM 23576(已经有一个变量叫做 KBD 指向它了),改变它的值就意味着模拟输入。
关于显示器,我们的模拟器是一个 256*512 的黑白屏幕(注意你的值的位数),它内存的起始点是 16384(又叫 SCREEN),单个位的值为1是黑色,为0是白色。

Lab04
这里一共有两个任务
Mult.asm: RAM[2] = RAM[0]*RAM[1]
Fill.asm: 当键盘有输入的时候,把整个屏幕变为黑色,否则白色。
详细的请自行阅读程序中的要求。

当你成功写好上面两个程序以后,你应该对 hack 下的汇编有一定的了解,所以接下来让我们看看它的原理。
首先,下面是我们整个计算机的构造:
[Image]

里面很多东西你应该都是知道的,其中,ROM 是我们给你的(它就像 RAM 一样,只不过是 ReadOnly ),它为 CPU 提供 指令。CPU 接受 指令, reset 信号 和 inM(也就是 M register),然后输出图上结果给 RAM,其中, writeM 用来判断是否需要更改 M ,(毕竟 A,D Register 都在CPU里面)。
[Image]
首先,我们要了解输入的 instruction 是什么。按照你写汇编的经验,这里肯定也是 A/C 两种指令。
A 指令:0xxxxxxxxxxxxxxx 也就是0开头,后边跟一个地址,简单好懂。
C 指令:111accccccdddjjj a 代表用 A 还是 M 寄存器,cccccc 代表了 ALU 计算,ddd 代表你赋值给谁,jjj 就是你的 jump 操作。
[Image]
CPU 的架构如上图我们已经给你了,你需要做的就是选出架构中的每一个 c,让 CPU 符合我们的逻辑。注意,当你构建 C 指令的时候,永远不要忘记还有 A 指令。
(其他有关的请自行查看代码注释和图表)
在写好 CPU 后,其他事情就简单了。首先是一个 RAM 构建:
[Image]
其实挺好看的,就是当你的值是 RAM 16K 里面,改 RAM16K,在 Screen 区间就是改 Screen , 在 Keyboard 就是改Keyboard。你可以自行观察下数据选择如何正确的知道该选择哪里。(RAM16K 是你以前写过的,Screen 和 Keyboard 是我们给你的,你可以使用 vscode 的自动补充查看抽象后的芯片需要和输出什么)
最后就是计算机的构建了,其实照着上面把 3 部分拼一下就可以了,这里不打算赘述。

Lab05
完成你的 CPU,Memory,Computer 芯片。

Week06
这一讲比较简单,本质上是让你写一个 汇编器 (Assembler),实现从 汇编语言 转换为 机器语言(16位)。其实具体的转法当你完成了 lab04 和 lab05 后应该已经心中有数了。这里简单叙述下要求:// 为注释,你需要忽略 // 后面的内容,同时,你需要忽略掉所有的空格。注意,实现的是 .asm -> .hack ,我们建议加入文件操作,就像 tools 里面给你的一样。

Lab06
写一个汇编器。

Tips
假如你遇见了困难,可以试着使用下面的项目结构:

  • 主体解决部分:实现两次 Pass,一次处理标签和变量,第二次实现转换。
  • SymbolTable:符号表,以 hash 的方式存下标签和变量。
  • IO:输入输出部分
  • Main:主函数
    当然,具体结构应该由你选择的语言规范和个人习惯来走。由于里面有一堆乱七八糟的转换,我们推荐你使用比较简单的语言快速实现(当然,c语言高手随意)。
    最后,如果你还没有编程基础,我们推荐你简单写(画)出思路就可以了。或者你可以尝试速通一门语言(这个项目很简单,1-2天的速通绰绰有余了应该,然后就是 GPT 大法,面向项目学习)。

标签:register,Image,RAM,指令,lab04,lab06,hack,Nand2tetris,CPU
From: https://www.cnblogs.com/hewo/p/18006713

相关文章

  • nand2tetris week4
    课程对应的汇编样例 //原代码段(c)/*arr=100;n=10;for(i=0;i<n;i++){arr[i]=-1;}*///第一部分,arr=100@100//将100存入A寄存器D=A//将A寄存器的值赋值到D寄存器(A是地址寄存器,D是数据寄存器)@arr//在ROM中为arr开辟一个空间,并将arr的地址赋予A寄存器M=D......
  • Lab06-04
    目录样本分析与前三个样本类似,增加了循环样本分析......
  • Lab06-03
    目录样本信息字符串信息导入表信息样本分析查杀思路样本信息与Lab06-01、Lab06-02类似,多出一个函数字符串信息导入表信息样本分析样本没有太多操作检查网络连接状态如果存在网络,访问http://www.practicalmalwareanalysis.com获取第5个字符根据返回的第5个字符做不......
  • Lab06-02
    目录与Lab06-01类似与Lab06-01类似......