IWKS 3300: NAND to Tetris Spring 2019 John K. Bennett Machine Language Foundations of Global Networked Computing: Building a Modern Computer From First Principles This course is based upon the work of Noam Nisan and Shimon Schocken. More information can be found at (www.nand2tetris.org).
Where we are: Abstract design Software Human abstract interface Thought hierarchy Chapters 9, 12 Compiler H.L. Language & abstract interface Chapters 10 - 11 Operating Sys. VM Translator Virtual abstract interface Machine Chapters 7 - 8 Assembly Language Assembler Chapter 6 abstract interface Computer Architecture Machine abstract interface Language Chapters 4 - 5 Gate Logic Hardware abstract interface Platform Chapters 1 - 3 Electrical Engineering Chips & Hardware Physics Logic Gates hierarchy
Assembly Language / Machine Code Abstraction – implementation duality: Assembly language (the instruction set architecture) can be viewed as a (sort-of) programmer-oriented abstraction of the hardware platform The hardware platform represents a physical means for realizing the assembly language / machine code abstraction Assembly Language and Machine Code Statements are Generally One-to-One: Symbolic assembly language statement, e.g., “ D=A ” That statement translates into executable binary, e.g., “ 1110110000010000 ” Assembly Language / Machine Code: Roughly speaking, machine code represents an agreed-upon formalism for manipulating data in memory using a processor and (usually) a set of registers. Assembly language syntax can differ widely across different hardware platforms.
Machine Code vs. Assembly 1010 0001 0010 1011 ADD R1, R2, R3 Evolution: Physical coding Symbolic documentation Symbolic coding Translation and execution Assembly requires Jacquard loom translation . Augusta Ada King, Countess of Lovelace (1801) (1815-1852)
Some Typical Assembly Language Commands // In what follows R1,R2,R3 are registers, PC is program counter, // and addr is some address in memory. ADD R1,R2,R3 // R1 R2 + R3 ADDI R1,R2,addr // R1 R2 + addr AND R1,R1,R2 // R1 R1 and R2 (bit-wise) JMP addr // PC addr JEQ R1,R2,addr // IF R1 == R2 THEN PC addr ELSE PC++ LOAD R1, addr // R1 RAM[addr] STORE R1, addr // RAM[addr] R1 NOP // Do nothing // Etc. – *many* variants
Three Address Architecture Consider the following code fragment: X = (A-B) / (C+(D*E)) // R1 ← Mem[A] Load R1, A // R2 ← Mem[B] Load R2, B // R3 ← R2 – R1 Sub R3, R2, R1 // R1 ← Mem[D] Load R1, D // R2 ← Mem[E] Load R2, E // R4 ← R1 * R2 Mpy R4, R1, R2 // R1 ← Mem[C] Load R1, C // R2 ← R1 + R4 Add R2, R1, R4 // R1 ← R3 / R2 Div R1, R3, R2 // Mem[X] ← R1 Store X, R1 There are typically a finite number of registers, on the order of 16-32 This code: 6 Memory references, code is not compact
Two Address Architecture Consider the following code fragment: X = (A-B) / (C+(D*E)) // R1 ← Mem[A] Load R1, A // R2 ← Mem[B] Load R2, B // R2 ← R2 – R1 Sub R2, R1 // R1 ← Mem[D] Load R1, D // R3 ← Mem[E] Load R3, E // R1 ← R1 * R3 Mpy R1, R3 // R4 ← Mem[C] Load R4, C // R1 ← R1 + R4 Add R1, R4 // R2 ← R2 / R1 Div R2, R1 // Mem[X] ← R2 Store X, R2 There are typically a finite number of registers, on the order of 16-32 This code: 6 Memory references, code is not compact
One Address Architecture Consider the following code fragment: X = (A-B) / (C+(D*E)) // Acc ← Mem[A] Load A // Acc ← Acc - Mem[B] Sub B // Mem[Temp1] ← Acc Store Temp1 // Acc ← Mem[D] Load D // Acc ← Acc * Mem[E] Mpy E // Acc ← Acc + Mem[C] Add C // Mem[Temp2] ← Acc Store Temp2 // Acc ← Mem[Temp1] Load Temp1 // Acc ← Acc / Mem[Temp2] Div Temp2 // Mem[X] ← Acc Store X There is one register, called the Accumulator This code: 10 Memory references, code is more compact
Zero Address Architecture Consider the following code fragment: X = (A-B) / (C+(D*E)) // SP = SP + 1; Mem[SP] ← Mem[D]; Push D // SP = SP + 1; Mem[SP] ← Mem[E]; Push E // Mem[SP- 1] ← Mem[SP] * Mem[SP -1]; Mpy // SP = SP -1 // SP = SP + 1; Mem[SP] ← Mem[C] Push C // Mem[SP- 1] ← Mem[SP] + Mem[SP -1] Add // SP = SP -1 // SP = SP + 1; Mem[SP] ← Mem[A] Push A // SP = SP + 1; Mem[SP] ← Mem[B] Push B // Mem[SP- 1] ← Mem[SP] - Mem[SP-1]; Sub // SP = SP -1 // Mem[SP- 1] ← Mem[SP] / Mem[SP -1] Div // Mem[X] ← Mem[SP]; SP = SP - 1 Pop X 24 Memory references, code is very compact
The Hack Computer A 16-bit machine (this means that the ALU and memory width are 16 bits) consisting of the following elements: RAM – an addressable sequence of registers* Data memory: ROM – an addressable sequence of registers* Instruction memory: D , A, M, where M stands for RAM[A] Registers: ALU, capable of computing various functions Processing: PC, holding an address Program counter: Control: The ROM is loaded with a sequence of 16-bit instructions, one per memory location, beginning at address 0. These instructions are fetched and executed in sequence until a jump instruction is encountered, at which time the PC is set to the jump address. Simple Instruction set: Only two Instructions: A-instruction, C- instruction; A fair amount of complexity is packed into C-instructions * Hack computer only; Recall that real memory is not implemented using registers.
The Hack CPU (no control shown)
The Hack Computer
Hack Assembly and VM Code Hack Assembly is a hybrid (1/2 address) code, but has only two kinds of instructions (Chapters 4, 5 & 6) Hack VM is zero address (wait for Chapters 7 & 8)
A Hack Machine Language Example Jack Code // Adds 1+…+100. var int i, sum; let i =1; let sum = 0; while (i < 101) { let sum = sum + 1; let i = i + 1; }
A-Instructions @ value // Where value is either a non-negative decimal number Symbolic: // or a symbol referring to such number. value (v = 0 or 1) 0 v v v v v v v v v v v v v v v Binary: Translation to binary: If value represents a non-negative number, see next slide We will handle the case when value is a symbol in Chapter 6 (Assembler).
A Instructions @ value // A value Where value is either a non-negative number or a symbol referring to a number. Coding example: Used for: Entering a constant value @17 // A = 17 ( A = value ) D = A // D = 17 Selecting a RAM location @17 // A = 17 D = M // D = RAM[17] ( register = RAM[A] ) Selecting a ROM location @17 // A = 17 JMP // branch to and fetch the ( PC = A ) // instruction stored in ROM[17]
C-Instructions - Lots Going On Symbolic: dest = comp ; jump // Either the dest or jump fields may be empty. // If dest is empty, the "=" is ommitted; // If jump is empty, the ";" is omitted. comp dest jump 1 1 1 a c1 c2 c3 c4 c5 c6 d1 d2 d3 j1 j2 j3 Binary:
The Comp Field Determines ALU Output (a and c1-c6) c1-c6 of the Comp Field are identical to ALU control inputs The ‘a’ bit chooses ‘A’ or ‘M’ as the Y input to the ALU (the X ALU input is always D).
The A-Register/M Multiplexor (and ALU Out Data Path) D x D register a -bit ALU out A A register A/M Mux y RAM M address input (selected register) Control Signals Control Logic address ROM Instruction input PC (selected register)
The Hack CPU (where the control signals go)
The Hack Computer
The Dest Field Each bit designates a destination (A, D, or M): A D M
The Jump Field The effects of j1-j3 are related to the zr and ng ALU output bits: j1 (out < 0): ng j2 (out = 0 ): zr j3 (out > 0): ng NOR zr
The C-Instruction Exercise 1: Implement the following tasks Using Hack Assembly and Machine Possible Destinations Code: dest = n + s Set D to A-1 dest = n - s Set both A and D to A + 1 dest = n Set D to 19 dest = 0 Set both A and D to A + D dest = 1 dest = -1 Set RAM[5034] to D - 1 Set RAM[53] to 171 n = {A , D , M} Add 1 to RAM[7], s = {A , D , M , 1} and store the result in D . dest = {A , D , M , MD , A , AM , AD , AMD , null}
The C-Instruction Exercise 2: Implement the following code dest = x + y using Hack Assembly Language: dest = x - y sum = 0 dest = x j = j + 1 dest = 0 q = sum + 12 – j dest = 1 arr[3] = -1 dest = -1 arr[j] = 0 x = {A , D , M} y = {A , D , M , 1} arr[j] = 17 dest = {A , D , M , MD , A , AM , AD , AMD , null} Symbol table: j 3012 (Symbols and values are sum 4500 arbitrary examples) q 3812 arr 20561
Control (focus on the yellow chips) D D register a -bit ALU A A register A/M Mux RAM M address input (selected register) In the Hack architecture: ROM = instruction memory Program = sequence of 16-bit address numbers, starting at ROM Instruction input ROM[0] PC (selected register) Current instruction = ROM[PC] To select instruction n from the ROM , we set A to n , using the instruction @n
Recommend
More recommend