What's the difference between A and M?

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

What's the difference between A and M?

riverfish
I'm trying to get my head around the A and M registers.

As far I have understood, A can be both a data value or a memory address.

And M = RAM[A]. Therefore M is a data value and therefore both A and M are data values. Is this correct?

If so, when do you use A and when do you use M as a data value?

Take for example 4.2 in the book which adds 1 + .. + 100:

// Adds 1+...+100.
@i // i refers to some mem. location.
M=1 // i=1
@sum // sum refers to some mem. location.
M=0 // sum=0
(LOOP)
@i
D=M // D=i
@100
D=D-A // D=i-100
@END
D;JGT // If (i-100)>0 goto END
@i
D=M // D=i
@sum
M=D+M // sum=sum+i
@i
M=M+1 // i=i+1
@LOOP
0;JMP // Goto LOOP
(END)
@END
0;JMP // Infinite loop

Near the top of the loop, you see the expression:
@100
D = D - A         // D = i - 100

In this expression I cannot explain why it's D=D-A instead of D=D-M.

From what I understand, @100 points A to memory address 100. But as to what the value is stored inside of memory address 100 is not known.

In that case, you can set M = 100, so RAM[100] = 100. Therefore, to get D = i - 100, the last statement should be D=D-M.

Please explain to me why this is not the case.
Reply | Threaded
Open this post in threaded view
|

Re: What's the difference between A and M?

ivant
The HACK CPU has 2 operational registers: A and D. You can think of them as boxes, each of which containing a single value at any given time.

For example, the assembly instruction @100 will store the value 100 in A. Let's say the next instruction is D=A, this will copy the value from A in D, so now both registers will contain the value 100. So, when you mention the register as "A" you are referring either to the "box" (as in A=-1) or to the value in it (D=A+1).

So, what is M then? M is a another way to treat the value in A. Suppose that A=100. If you write M=0, you are saying "store in the memory with address 100 the value 0." And if you write D=M-1, you are saying "get the value, stored in address 100 in memory, subtract 1 from it and store the result in the register D."

M gives the CPU the ability to access the RAM. Either to read it or to write it, or even both, like in M=M+1.

You can treat A either as value or as an address (which people sometime refer to as pointer, because that's what it's called in C and other languages). A can also be used as jump target, in which case it "points" to a memory location in the ROM. For example the instruction "D;JGT" tells the processor to check if the value stored in the register D is greater than 0, and if so, to load the next instruction from the ROM address, which is stored in the register A.

So A has 3 main uses: as storage for a singe value (or the value itself); as RAM address; or as a ROM address. To access the value, stored in the register A, you use A.

To access a RAM cell (or RAM register), you first have to make sure that its address is stored in A and you use M.

To jump to a ROM address, you first store it in A (for example with the instruction @sum) and then you use one of the jump instructions.
Reply | Threaded
Open this post in threaded view
|

Re: What's the difference between A and M?

riverfish
Hey Ivant,

In your example, you alluded to the fact that A is both a data value and a memory address.

So when you declare @100, is A storing the value 100 or is 100 the address that A is pointing to, or both? I think this is what is confusing the hell out of me.

Everything else like D and M is quite clear to me. It's just A that I can't get my head around!
Reply | Threaded
Open this post in threaded view
|

Re: What's the difference between A and M?

cadet1620
Administrator
This post was updated on .
The value of A is just a bit pattern. The interpretation of what that bit pattern represents depends on how the A register is used.
@100    // Put the bit pattern 0000 0000 0110 0100 (decimal 100) into the A register.
D=A     // D = 100          using the A register's value as data
D=D+A   // D = 200          using the A register's value as data
M=D     // RAM[100] = 200   using the A register's value as a RAM memory address
0;JMP   // Set the PC to address 100. The next instruction will be read from ROM[100]
Normally, the various usages are not mixed together as in the above example so you see common sequences like
@123    // D = 123
D=A


(CONTINUE_LOOP)
...
@CONTINUE_LOOP  // goto top of loop 
0;JMP


@16         // counter = 16
D=A
@counter
M=D
...
@counter    // decrement counter
M=M-1
In that last example, "counter" is not mentioned in any () code label, so it is automatically assigned a RAM location.

Check out Introduction to Hack Assembly Language. It may help. If you have any suggestions for improving it, please let me know.

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

Re: What's the difference between A and M?

riverfish
cadet1620 wrote
The value of A is just a bit pattern. The interpretation of what that bit pattern represents depends on how the A register is used.
@100    // Put the bit pattern 0000 0000 0110 0100 (decimal 100) into the A register.
D=A     // D = 100          using the A register's value as data
D=D+A   // D = 200          using the A register's value as data
M=D     // RAM[100] = 200   using the A register's value as a RAM memory address
0;JMP   // Set the PC to address 100. The next instruction will be read from ROM[100]
Normally, the various usages are not mixed together as in the above example so you see common sequences like
@123    // D = 123
D=A


(CONTINUE_LOOP)
...
@CONTINUE_LOOP  // goto top of loop 
0;JMP


@16         // counter = 16
D=A
@counter
M=D
...
@counter    // decrement counter
M=M-1
In that last example, "counter" is not mentioned in any () code label, so it is automatically assigned a RAM location.

Check out Introduction to Hack Assembly Language. It may help. If you have any suggestions for improving it, please let me know.

--Mark

Going back to your example, if you declare @100, then the value of A = 100 , i.e. the A register reads 0000 0000 0110 0100. Is this right?

And if M is a register that is pointing to a memory address of A, i.e. M = RAM[A]. Then in this case, M is pointing to slot in memory with the address 100 right? For example, if RAM has 1000 slots, then slot 100 corresponds to the value of M. If so, what is the value of M in that address of 100 then?

Reply | Threaded
Open this post in threaded view
|

Re: What's the difference between A and M?

cadet1620
Administrator
riverfish wrote
Going back to your example, if you declare @100, then the value of A = 100 , i.e. the A register reads 0000 0000 0110 0100. Is this right?
Correct.
And if M is a register that is pointing to a memory address of A, i.e. M = RAM[A]. Then in this case, M is pointing to slot in memory with the address 100 right? For example, if RAM has 1000 slots, then slot 100 corresponds to the value of M.
Correct.
 If so, what is the value of M in that address of 100 then?
It might help if you discard the idea of M being a "register". Think of M as a gateway to RAM. Every M in Hack assembly language means RAM[A].

RAM keeps the last value that was written to it. Once you write something to RAM[100], that value will stay there until a different value is written to RAM[100].

In the real world, if you read a RAM location that has never been written to, you will get an undefined value.  It is important to initialize RAM variables before you use them. (In the n2t tools, RAM is initialized to 0 when the tool starts. Some of the tools reset the RAM to 0 when you restart your program, some of the tools do not. Don't rely on RAM being zeroed.)

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

Re: What's the difference between A and M?

riverfish
cadet1620 wrote
riverfish wrote
Going back to your example, if you declare @100, then the value of A = 100 , i.e. the A register reads 0000 0000 0110 0100. Is this right?
Correct.
And if M is a register that is pointing to a memory address of A, i.e. M = RAM[A]. Then in this case, M is pointing to slot in memory with the address 100 right? For example, if RAM has 1000 slots, then slot 100 corresponds to the value of M.
Correct.
 If so, what is the value of M in that address of 100 then?
It might help if you discard the idea of M being a "register". Think of M as a gateway to RAM. Every M in Hack assembly language means RAM[A].

RAM keeps the last value that was written to it. Once you write something to RAM[100], that value will stay there until a different value is written to RAM[100].

In the real world, if you read a RAM location that has never been written to, you will get an undefined value.  It is important to initialize RAM variables before you use them. (In the n2t tools, RAM is initialized to 0 when the tool starts. Some of the tools reset the RAM to 0 when you restart your program, some of the tools do not. Don't rely on RAM being zeroed.)

--Mark
I completely understand what you've just said. Going back to example 4.2 though, there's a piece of code that I want to clarify with you:

@i
D=M // D=i
@sum
M=D+M // sum=sum+i

@i declares a variable 'i', which is basically a pointer to a memory address. What the value and address of this variable is unknown, but address is likely to be address 16 since 0-15 are reserved.

We know that A = i.

And M equals to the address that i is pointing to. Since i is a variable, let's assume that it's pointing to address 16. Therefore M = RAM[16]. And because i = RAM[16], we can conclude that M = i and subsequently, A = M.

Is my thought process correct here?
Reply | Threaded
Open this post in threaded view
|

Re: What's the difference between A and M?

cadet1620
Administrator
I think that you have the concepts, but the nomenclature is a bit off.

Variable "i"s address is 16. That is where the assembler placed (allocated) it in the RAM.
@i loads the address of "i" into the A register. The A register now contains a pointer to "i".

A variable can be a pointer if its purpose is to hold the address of another variable or an address of somewhere defined in memory. For instance, for the Fill program you will be writing to the Screen which is RAM starting at 16384. You might want to use a pointer variable to operate on screen memory.
@SCREEN     // built in symbol for Screen starting address
D=A
@scrPtr     // A = scrPtr's address
M=D         // scrPtr's value = 16384
...
@scrPtr     // A = scrPtr's address
A=M         // A = scrPtr's value -- the pointer to Screen memory
M=1         // RAM[scrPtr] = 1
...
@scrPtr     // A = scrPtr's address
M=M+1       // scrPtr = scrPtr+1 -- now points to the next word of Screen memory
--Mark
Reply | Threaded
Open this post in threaded view
|

Re: What's the difference between A and M?

riverfish
Makes sense now. I think the key point that made me understand all this is that the data value of the A-register is an address. Thanks
Reply | Threaded
Open this post in threaded view
|

Re: What's the difference between A and M?

A_Random_Person
In reply to this post by riverfish
A can be used for going to a address without using "@", or it can be used to assign RAM[n] to a number that is not -1, 0, or 1 (for those three numbers you just enter M=-1, M=0, or M=1). The M register is used for selecting the contents of the RAM[n] or setting the contents of RAM[n] to something (for example, if you want to set RAM[0] to 1, this is the code you use:

@0
M=1


Hope that helped!