nand2teris_lecture04

Nand2teris04 机器语言

机器语言概要:

机器语言分为两种,汇编语言和二进制语言

机器语言主要操控着三个底层硬件:处理器cpu,内存memory和寄存器register

机器语言利用处理器和寄存器来操控内存

处理器,内存和寄存器的简单介绍:

  • 内存:储存数据和指令的硬件设备,数据和指令均为二进制数。
  • 处理器:对数据和指令进行一些操作,比如从内存或寄存器中存入或取出数据或指令,将数据进行算术操作,指令进行逻辑操作。
  • 寄存器:临时存放一些数据或指令,方便处理器计算

两种机器语言

  • 二进制语言:在16位计算机上,左边4位代表着cpu的操作编码,后面的12位标识此次操作的操作数。
  • 汇编语言:由于二进制语言晦涩难懂,采用助记符的形式代表二进制语言。助记符可以表示底层硬件和二进制操作。例如1010001100011001这串二进制代码中,前面4位操作编码1010可用add助记符表示,后面12位可用R0~R15助记符来表示,整串代码可表示为Add R3,R1,R9

不同的计算机,其汇编语法也各不相同,下面介绍通用的语法。

寻址方式

  • 直接寻址:直接表示一个指定内存单元的地址,这在A寄存器中很常用

例:LOAD R1,67 // R1 🡨 Memory [67]

  • 立即寻址:将常数加载到寄存器中,而不是作为内存单元的地址,这在D寄存器中很常用

例:LOAD R1,67 // R1 🡨 67

  • 间接寻址:不直接的表示一个指定内存单元的地址

例:ADD x,6,7 // x = 6+7

LOAD R1,x // R1 🡨 Memory [x]

控制流程

命令之间通过控制流程来跳转。控制流程包括循环,条件语句,无条件跳转和子程序调用

Hack机器语言概述

  • Hack机器语言(汇编语言和二进制语言)能通过指令轻易的操控Hack机器中的两个寄存器 D寄存器A寄存器

D寄存器存储数据值,A寄存器存储数据值,数据值和指令值的地址

  • Hack机器语言的指令有两种操控方式:算术指令和逻辑指令

在算术指令中,CPU会将计算的返回结果返回到D寄存器暂存,

例如:D = Memory [516] -1 CPU从内存地址为516的内存单元(这里假设为数据内存)中取值,将计算结果存储到D寄存器。这条算术指令也可以表示为D = M -1,这里M表示的也是内存单元的值

    • 算术指令详解:

算术指令前后可分为三个部分

  1. 计算什么
  2. 将计算后的值存储到什么地方
  3. 下一步做什么
      • 计算什么

算术指令(以下简称C指令)的comp域是规定要计算的内容。Comp域通过128个函数指明了ALU该如何计算,计算什么。

例如:1110 0011 1000 0000 表示让ALU进行D-1的操作,即D寄存器当前值减1.

(当a=1)

Comp助记符

      • 将计算后的值存储到什么地方

C指令的dest域决定着计算结果所要保存的目的地,

d1决定着是否将计算结果存入A寄存器(存入地址),d2决定着是否将计算结果存入到D寄存器(存入数值),d3决定着是否将计算结果存入到M内存单元。

例如:0000 0000 0000 0111 //@7

1111 1101 1101 1000 //M,D = M+1

表示的就是将A寄存器的值,设为7,然后将内存单元memory[7]的值加1,存入内存单元和D寄存器

      • 下一步做什么

C指令的jump域告诉计算机下一步将执行什么命令。Jump域的三个位:

J1规定:当ALU输出值小于0,发生跳转

J2规定:当ALU输出值等于0,发生跳转

J3规定:当ALU输出值大于0,发生跳转

所以当C指令的comp域执行完成后,将执行结果保存到dest域,执行结果的大小与jump域的条件结合,决定当前指令需不需要跳转到下一条指令。下一条指令的地址由A寄存器保留。

Hack机器语言

二进制语言

汇编语言

逻辑指令

算术指令

数据内存

指令内存

    • 逻辑指令详解

在逻辑指令中,cpu会按照A寄存器中存储的值(地址值),从指令内存中取值,执行一系列例如jump跳转,while循环的逻辑操作,从一条指令跳转到另一条指令,指令的地址由A寄存器保存。

A寄存器中的值通过A指令设置。

(图为A指令介绍)

例如@5,将5的二进制形式存储到A寄存器中。表示Memory[5],

汇编符号

汇编语言中除了汇编指令,另一板块就是汇编符号,下面介绍三种汇编符号

  • 预定义符号:

虚拟寄存器:R0~R15用来代表0到15号RAM地址

预定义指针:SP、LCL、ARG、THIS、THAT也被用来代表0到4号RAM地址

I/O指针:SCREEN和KBD被用来表示RAM地址16384(0x4000)和24576(0x600),这两个地址也分别表示屏幕和键盘内存地址

  • 标签符号:

用户自定义的符号,由伪命令“(xxx)”来声明,符号只能被自定义一次。用来标记goto命令跳转的地址。Xxx的RAM地址代表着下一条指令的地址,这在后面的汇编编译器章节有说明。自定义的符号可以在汇编程序中的任何地方使用。

(由于伪指令xxx经过汇编器翻译后不会产生任何二进制代码,所以称为伪指令)

  • 变量符号:

在汇编程序中任何用户定义的符号xxx,如果它不是预定义符号,也不是使用“(xxx)”的标签符号,那么就被看作是变量,并被汇编程序赋予独立的内存地址,从RAM地址16,即0x0010开始。

关于汇编语言和二进制语言的联系

  • 汇编语言文件以.asm命名,二进制语言文件以.jack命名。
  • 汇编语言文件由文本行组成,每一行代表着一条指令或者一个符号定义;二进制语言文件也由文本行组成,第n行二进制码被存储到指令内存RAM的地址为n的单元(RAM[n])

一些补充声明:

  • 常数(constants)和符号( symbols):常数必须是非负的而且总是用十进制表示。用户自定义的符号可以是任何字母、数字、下划线(_ )、点(.)、美元符号($)、 冒号(:)构成的字符串,但它不能以数字开头。
  • 注释以双斜线 (//) 开头,并到本行结束符之前(不换行)的文本被认为是注释,不被程序执行。
  • 空格空格字符及空行也被程序忽略。
  • 大小写:所有的汇编助记符必须大写。其他的比如用户自定义标签(label) 和变量名

则要区分大小写。一般是标签大写,变量名小写。

posted @ 2022-12-30 20:32  群山象  阅读(17)  评论(0)    收藏  举报