not getting it

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

not getting it

huskeyw
So I have done assembly programming.. used to doing
LD a,1
Add A, 1

and getting A = A + 1 = 2

which means a simple multiplication loop is to add a to its self as many times as the value of the second number..

like so:
MathMul:
        ld a,b ; copy b reg to a, b will be our counter
        cp 0 ; if b = 0 (CP = compute)
             jr z, SaveResult ; store result jump to relative local address Save Result
        xor a ;ld a,0 ; counter
MathMultagian:
        add c ; now add c to a (implicit add to A)
        djnz MathMultagian ; jump with decrease till zero only works with b register
jr SaveResult



but in this assembly it makes no sense.. its like a bad version of the WAZ monitor and assembly

If I take a address
@R0

and then I should be able to do M=M+M but that does not work (its illegal.. )
So I do D=M (which should assine D to the Value in the memory location) and then do a M = A+D

@R0
M=A+D
I should get the memory address is now assigned the value of A+D

as a whole  ( assine R0 a value of 2 in the cpu emulator)
@R0
D=M //assine value from R0 to the D register
M=A+D // assine back A which should be the value in memory as well, plus D (so 2+2 ) and save that to R0


and that does nothing..  

and yes I have read the reference and watched the videos.. and it makes no sense, seams like a lot of expected knowledge
Reply | Threaded
Open this post in threaded view
|

Re: not getting it

WBahn
Administrator
huskeyw wrote
If I take a address
@R0

and then I should be able to do M=M+M but that does not work (its illegal.. )
No, you shouldn't be able to do that. Look at the hardware. To add two things together, you have to get the two things to the inputs of the ALU. However, one input of the ALU is ALWAYS the contents of the D register. The other is either the contents of the A register, or the contents of the memory location whose address is in the A register.

Your logic has to reflect the capabilities of the hardware. The Hack hardware is extremely limited (though even so it is capable of doing things that most "real" hardware is not capable of). Furthermore, the Hack is quite on par with many low-end embedded microcontrollers where cost is everything; the low end PIC lines from Microchip, such as the PIC 16C54, had members that had 33 instructions (which included controlling several peripherals), a single register and just 18 bytes of RAM. That's it.

So I do D=M (which should assine D to the Value in the memory location) and then do a M = A+D
I think you mean the right thing, but you are saying it backwards.

If assigns the value in the memory location to the D register -- the value in D is changed, the value in M is not.

If you do M = A + D, then you are changing the value stored in the memory location whose address is in A and setting it to the sum of the value in D and the value in A, which is an ADDRESS.

Think about whether you really want to do that.

You probably want to do

M = D + M

or perhaps

D = D + M

depending on your overall algorithm.

@R0
M=A+D
I should get the memory address is now assigned the value of A+D
A has a value of 0 (that's what the instruction @R0 did -- set A to 0); don't lose sight of that.

Try taking a piece of paper and put four columns on it -- Instruction, D, A, and M. Then track the contents of those three memory locations as each instruction is executed. Any time A changes, M changes (though, of course, the actual value could end up being the same if those two memory locations just happen to have the same values stored in them).
Reply | Threaded
Open this post in threaded view
|

Re: not getting it

huskeyw


I can't get this emulator to behave or do the same thing twice..  

and its  not doing what you suggested..
if I do (note I preset the value of R0 as 8 and of R1 as 8)
@R1
M=M-1 //decrements value in R1  same as a i--
@R2
D=M
@5
M=D

memory location 5 should = the value in memory location 2 (R2), in this case 8   .. no?
 
but if I do it this way in the emulator I get zero (0) in memory location 5 (tried R5 same thing)


If I change it to

@R2
D=A
@5
M=D

Memory location 5 gets the value 2.. not the number in memory but the address.. this is a pointer with no sense way to pull that pointer back.. or a good explanation in any of the material how..
but .. and if I do
        M=M-1  subtracts the value in Memory so M acts on memory there
if I do

@R0
D=M  //assine memory to d register
@R0
M=M+D // Add A register to its self same as R0=R0+R0

this works..

so why does not the first..

and I programmed Pic's for 25 years.. its syntax is much clearer..  the code before was from a Z80 which I can emulate on a PIC.. is not complex hardware
Reply | Threaded
Open this post in threaded view
|

Re: not getting it

huskeyw
so how do I store a value and use it to test against..

in the example they use memory locations as a value.. well that does not work if I need to test against the value 1 while using memory location 1 to store a value..
Reply | Threaded
Open this post in threaded view
|

Re: not getting it

huskeyw
ok after all my bitching I think I figured this out..

so this compiler mixes address with values.. which means you need to assign values before you start storing any data.. (no separation between program space and data space.. )

so at a high level I had to do this for multiplication..

Set a value (its a memory location ) first and then assines the value of that to a memory location elsewhere


        @16
                D=A
        @R0
                M=D
This set R0 to the Value 16..  now 16 is free to use
it takes to different memory address to do any function..

@R5
    D=M //places the data in memory location 5 on the D Register
@R0
    M=M+D // Add  register to memory at location 0 and over writes it,  same as R0=R0+R0


had to figure out jumps.. had to put a jump at the end of my loop going to the top while testing at each change..  not part of this thread.. but I am used to a RTN in assembly so it will terminate code sections..

need to get some testing of when my counter becomes negative..


Reply | Threaded
Open this post in threaded view
|

Re: not getting it

WBahn
Administrator
There is a HARD separation between program memory and data memory -- more so even than in the PICs.

The program is stored in the Instruction ROM and the data is stored in the data RAM and never the twain shall meet. In the PIC (at least the older generations that I used to use) you can put data tables in the program memory and get data from them using RETLW and such. There is no means of doing that with the Hack -- or at least not nearly as elegant and compact. This is why the font tables are stored in data RAM instead of in the ROM. It's also why the PICs could get by with processors have as few as just 18 bytes of total RAM -- you could use the ROM for static data.

I don't know what you mean when you say 16 is free to use.

When you perform

@16

That is just putting the value 16 into the A register. Nothing more, nothing less. It's just a number. What it means depends entirely on how you subsequently use the A register.

You can use it as a general purpose register to hold data. However...

Whenever you execute an instruction that accesses the data RAM, the address of the cell accessed has to be in the A register. Period. No exceptions.

Whenever you execute a jump instruction, the address of the target instruction in the instruction ROM has to be in the A register. Period. No exceptions.

Thus, you need to be sure that you do not try to execute an instruction that both accesses RAM and performs a jump -- the A register can only be used for one or the other in a given instruction (that the address of the RAM cell you want to access happens to be the same as the instruction address you want to jump to is a theoretical possibility and you could certainly craft code very carefully that did it, but in almost all real situations this would be a logic error).

Not that the olden day PICs could not perform computed gotos -- you could conditionally skip the next and that was it -- the skipped instruction was usually an unconditional goto to a precomputed target known at compilation time. The ability to do jumps that are computed at runtime is a significant increase in the power of the machine, though like most such things it is something relatively few programmers take advantage of.

Reply | Threaded
Open this post in threaded view
|

Re: not getting it

huskeyw
I thank you for helping, lets start there and I am trying to get this assembler strait and you have filled in gaps from the training which I feel is expecting some knowledge.. but because of the level of understanding by the instructors they can't see the gaps.. I think writing a few more traditional programs would teach the assembler better.

 

but to my point as to what I am seeing and maybe it will help someone else..

So when I
        @8     //value of 8
        D=A  //assine 8 to D
        @R1 //change to memory location 1
        M=D // place 8 from the D register into memory R1..  (non of this happens BTW in the emulator)

I run this and nothing.. looking at memory, I get nothing placed in R1

So next step in understanding.. I put in the CPU emulator a 8 in Memory location 8 and now that code places the data from memory location 8 into R1 if it is already placed in location 8..

now the issue on why I think its inconsistent.. and I can't figure out when it does one operation or the other..

in the example program we have
    @100    // addr = 100
     D=A      
     @addr
     M=D


so why does it on the example place 100 in register D and then place 100 in the @addr (memory location 16 when this is the first variable) in this example?? its the same code with a different address.
why does mine not set the value 8 and I have to preset it in the CPU? when there example sets 100 with the same code



Reply | Threaded
Open this post in threaded view
|

Re: not getting it

huskeyw
it must be an issue with the emulator..
I can get it to work and then it stops working with the same code..

when it works..
A takes the memory address as a value and M takes the value in memory..

and restart the simulator for every run.. painful..
Reply | Threaded
Open this post in threaded view
|

Re: not getting it

WBahn
Administrator
In reply to this post by huskeyw
huskeyw wrote
I thank you for helping, lets start there and I am trying to get this assembler strait and you have filled in gaps from the training which I feel is expecting some knowledge.. but because of the level of understanding by the instructors they can't see the gaps.. I think writing a few more traditional programs would teach the assembler better.

 

but to my point as to what I am seeing and maybe it will help someone else..

So when I
        @8     //value of 8
        D=A  //assine 8 to D
        @R1 //change to memory location 1
        M=D // place 8 from the D register into memory R1..  (non of this happens BTW in the emulator)

I run this and nothing.. looking at memory, I get nothing placed in R1
I don't know what your problem is. I have no problem seeing the effect. I copied your code, tabs, spaces, comments, mispellings and all) into a file and loaded it in the CPU emulator and when I ran it the value in memory location 1 became 8.

You might try turning on the program flow and animation so that you can visually track where things are going.

Where are you looking for R1? Remember, it's just address 1 in the RAM.

So next step in understanding.. I put in the CPU emulator a 8 in Memory location 8 and now that code places the data from memory location 8 into R1 if it is already placed in location 8..

now the issue on why I think its inconsistent.. and I can't figure out when it does one operation or the other..

in the example program we have
    @100    // addr = 100
     D=A      
     @addr
     M=D


so why does it on the example place 100 in register D and then place 100 in the @addr (memory location 16 when this is the first variable) in this example?? its the same code with a different address.
why does mine not set the value 8 and I have to preset it in the CPU? when there example sets 100 with the same code
Reply | Threaded
Open this post in threaded view
|

Re: not getting it

WBahn
Administrator
In reply to this post by huskeyw

I can virtually guarantee it is not an issue with the emulator.

Are those four instructions the ONLY instructions in your ENTIRE .asm file?

If not, make a file that has ONLY those four instructions.

You might also send me the actual file that is causing you problems and I can take a look at it when I get a chance.
huskeyw wrote
it must be an issue with the emulator..
I can get it to work and then it stops working with the same code..

when it works..
A takes the memory address as a value and M takes the value in memory..

and restart the simulator for every run.. painful..
Reply | Threaded
Open this post in threaded view
|

Re: not getting it

huskeyw
it the only 4 instructions, reload simulator and reload the file and it works.. run a few times and it does odd things.. still don't have the syntax down for other things..
Reply | Threaded
Open this post in threaded view
|

Re: not getting it

huskeyw
what I am not getting now is how to write to a memory address with out declaring it..

say SCREEN, I assume I can not increment the built in..
So I create a pos variable (memory location 17) and I write the address of SCREEN in POS, and incrament POS.. simple (now)..

now how do I write to the memory address located in POS? I dont want to write to memory location 17, but use POS as a pointer..

I tried what I thougt would work
@POS
   A=M //Assine the A register the value of memory (screen +)
   M=D // not good example but D was assigned to a value before this, say its 011111111111111111 so I thought this would put D into the Memory location loaded in the A register.

Reply | Threaded
Open this post in threaded view
|

Re: not getting it

huskeyw
@POS
        M=M+1
@i
        D=M
@POS
        A=M
        M=D

it works now.. here is the whole, not sure why it did not work before, I started indenting under memory so its easy to see commands effecting that memory call.