Supplied Assembler sets strange address

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

Supplied Assembler sets strange address

linse
When assembling Max.asm, the supplied assembler sets the first instance of the symbol address @OUTPUT_FIRST to 1010 (10 in decimal). And then the first instance of @OUTPUT_D to 1100 (12) and finally @INFINITE_LOOP to 1110 (14). I can't for the life of me think why this might be.

Running on Darwin, Mac OS X 10.9.3.

Can anyone help?
Reply | Threaded
Open this post in threaded view
|

Re: Supplied Assembler sets strange address

ybakos
Hints:

Does Max.asm contain labels? If so, what are they? What lines of assembly do the labels correspond to?

Reply | Threaded
Open this post in threaded view
|

Re: Supplied Assembler sets strange address

AnalyticLunatic
Hey ybakos, I've been sitting here reviewing your *Hint* and I am just not making a connection?

I see like mentioned that the following get translated:

@OUTPUT_FIRST = 0000 0000 0000 1010 (10)
@OUTPUT_D = 0000 0000 0000 1100 (12)
@INFINITE_LOOP = 0000 0000 0000 1110 (14)

And below is the Max.asm file. No matter how I look through it (comments, no comments) I am not seeing how/why the 10/12/14 values are being chosen? At first I had set these 3 values in a reference Dictionary in my code and it worked no problem for Max.asm file, but then on Rect.asm file the @INFINITE_LOOP was coming in as 0000 0000 0001 0111 (23) instead???

Max.asm:

// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/06/max/Max.asm

// Computes R2 = max(R0, R1)  (R0,R1,R2 refer to  RAM[0],RAM[1],RAM[2])

   @R0
   D=M              // D = first number
   @R1
   D=D-M            // D = first number - second number
   @OUTPUT_FIRST
   D;JGT            // if D>0 (first is greater) goto output_first
   @R1
   D=M              // D = second number
   @OUTPUT_D
   0;JMP            // goto output_d
(OUTPUT_FIRST)
   @R0            
   D=M              // D = first number
(OUTPUT_D)
   @R2
   M=D              // M[2] = D (greatest number)
(INFINITE_LOOP)
   @INFINITE_LOOP
   0;JMP            // infinite loop
Reply | Threaded
Open this post in threaded view
|

Re: Supplied Assembler sets strange address

cadet1620
Administrator
It's not the source code line numbers that matter. The values for the symbols are the ROM address of the corresponding label: (OUTPUT_FIRST), etc.

Here's the listing file that my assembler generates for Max.asm.
The columns are:
  Source line number,
  ROM address for the instruction,
  Instruction code (decimal for A-instructions, hexadecimal for C-instructions),
  Source line.
 1:             // This file is part of www.nand2tetris.org
 2:             // and the book "The Elements of Computing Systems"
 3:             // by Nisan and Schocken, MIT Press.
 4:             // File name: projects/06/max/Max.asm
 5:  
 6:             // Computes R2 = max(R0, R1)  (R0,R1,R2 refer to RAM[0],RAM[1],RAM[2])
 7:  
 8:    0     0     @R0
 9:    1  FC10     D=M              // D = first number
10:    2     1     @R1
11:    3  F4D0     D=D-M            // D = first number - second number
12:    4    10     @OUTPUT_FIRST
13:    5  E301     D;JGT            // if D>0 (first is greater) goto output_first
14:    6     1     @R1
15:    7  FC10     D=M              // D = second number
16:    8    12     @OUTPUT_D
17:    9  EA87     0;JMP            // goto output_d
18:   10        (OUTPUT_FIRST)
19:   10     0     @R0
20:   11  FC10     D=M              // D = first number
21:   12        (OUTPUT_D)
22:   12     2     @R2
23:   13  E308     M=D              // M[2] = D (greatest number)
24:   14        (INFINITE_LOOP)
25:   14    14     @INFINITE_LOOP
26:   15  EA87     0;JMP            // infinite loop
Notice that A-instructions and C-instructions each use 1 word of ROM memory, but Labels do not use any ROM.

Your Pass One code needs to keep track of how much ROM is required so that it can assign the correct ROM address to the labels it adds to the symbol table.

--Mark
Reply | Threaded
Open this post in threaded view
|

Re: Supplied Assembler sets strange address

AnalyticLunatic
@cadet1620 (Mark), I saw before how Labels (ex. "(Label)") were not being assigned a value directly per say during translation of the Assembler, but I am still not grasping the addressing for the @sometext commands.

Assuming your columns are actually:

Source Line Number,
Instruction Code,
ROM Address for the Instruction,
Source Code Line

I am not at all understanding why your values are going 0, FC10, 1, F4D0, 10, etc. (I get the R0, R1) for the ROM Addressing?

My current coding is going through a single pass, 1 line at a time, and correctly translates Add.asm and the various ***L.asm files, but the regular Max.asm, Pong.asm, and Rect.asm files are going wonky because I am not getting this ROM addressing thing.

Would it be possible for you to elaborate some more? I am just not seeing the light here. If it helps for any references, below is the corrected expected output based upon the provided Assembler:

Max.asm:

0000000000000000
1111110000010000
0000000000000001
1111010011010000
0000000000001010
1110001100000001
0000000000000001
1111110000010000
0000000000001100
1110101010000111
0000000000000000
1111110000010000
0000000000000010
1110001100001000
0000000000001110
1110101010000111
Reply | Threaded
Open this post in threaded view
|

Re: Supplied Assembler sets strange address

cadet1620
Administrator
As stated, second column is instruction's ROM address. Third column is instruction code.

Sorry about the mix of decimal and hexadecimal numbers.  My assembler outputs hex for the C-instructions because I can read the bit patterns quickly from hex numbers (an occupational hazard :-) but I want to see the decimal ROM addresses since that's what the n2t tools display.

This is what it looks like in binary:
 1:                                         // This file is part of www.nand2tetris.org
 2:                                         // and the book "The Elements of Computing Systems"
 3:                                         // by Nisan and Schocken, MIT Press.
 4:                                         // File name: projects/06/max/Max.asm
 5:
 6:                                         // Computes R2 = max(R0, R1)  (R0,R1,R2 refer to RAM[0],RAM[1],RAM[2])
 7:
 8: 0000000000000000    0000000000000000       @R0
 9: 0000000000000001    1111110000010000       D=M              // D = first number
10: 0000000000000010    0000000000000001       @R1
11: 0000000000000011    1111010011010000       D=D-M            // D = first number - second number
12: 0000000000000100    0000000000001010       @OUTPUT_FIRST
13: 0000000000000101    1110001100000001       D;JGT            // if D>0 (first is greater) goto output_first
14: 0000000000000110    0000000000000001       @R1
15: 0000000000000111    1111110000010000       D=M              // D = second number
16: 0000000000001000    0000000000001100       @OUTPUT_D
17: 0000000000001001    1110101010000111       0;JMP            // goto output_d
18: 0000000000001010                        (OUTPUT_FIRST)
19: 0000000000001010    0000000000000000       @R0
20: 0000000000001011    1111110000010000       D=M              // D = first number
21: 0000000000001100                        (OUTPUT_D)
22: 0000000000001100    0000000000000010       @R2
23: 0000000000001101    1110001100001000       M=D              // M[2] = D (greatest number)
24: 0000000000001110                        (INFINITE_LOOP)
25: 0000000000001110    0000000000001110       @INFINITE_LOOP
26: 0000000000001111    1110101010000111       0;JMP            // infinite loop
You can see in the third column the instructions in the Max.hack file.
Look at the second column for lines 18, 21, and 24. You can see the binary ROM address for the labels.
These are the same values that the symbols get as their instruction code when they are use in A-instructions.

--Mark
Reply | Threaded
Open this post in threaded view
|

Re: Supplied Assembler sets strange address

ivant
In reply to this post by AnalyticLunatic
You are creating a two-pass assembler. The job of the first pass is to find the correct values for the labels. For this you'll go through each instruction and see what would be it's address. And when you see a label instruction, you'll have to remember somewhere (e.g. in a map or dictionary) the label and the corresponding address.

In HACK machine language, each instruction has the same size: 1 word. So it's easy to find the addresses: just count the instructions, starting from 0, and skipping comments, empty lines and labels. So for max.asm, we'll have the following:

OUTPUT_FIRST = 10
OUTPUT_D = 12
INFINITE_LOOP = 14

In the next pass, the assembler will use these values to generate instructions like @INFINITE_LOOP, which would be equivalent to @14.

One thing that might be a bit confusing is, that there is ROM, which contains the program, and there is RAM, which contains the data and they both have addresses, starting from 0. The CPU addresses the ROM trough the Program Counter (PC) register. When it needs to make a jump, it assumes that the jump address (the address of the instruction in the ROM) is the value of the A register. So it moves the value of A (e.g. 14) to the PC (that is, PC=14) and the next instruction that it will execute is the one at address 14 (which is 0;JMP).

On the other hand, the CPU addresses the RAM through C instructions, which reference M, such as M=D or D=M or M=M+1, etc. The A register again contains the address of the memory, but this time in RAM.