简体   繁体   中英

Understanding Hack Assembly Language code

My teacher gave me this example code to learn from, I still don't understand it, to do with Assembly language code & nand2tetris. Can someone explain?

These are the parts I don't quite get yet:

                @R1 
                D=M //Load RAM[1] into D register
                @x  
                M=D
            
        (While loop)
                @x  
                D=M 
                @END
                D;JLE //if x <= 0, jump to END: how do you know x is <= 0 here? Also, what does the 'D;' mean?
         

        //some random codings in the middle...


        (End loop)  
                @END  //When jump to end,
                0;JMP //Infinite loop (program ends) -Is it like the '0;' here specifies that if x <= 0
    

--> thank you, maybe with different explanations I'll be able to get it:") I'm still a newbie please bear with me

There are at least 3 levels upon which to understand such code:

  1. What does each individual instruction do (each line of assembly)? These are explained in the tutorial texts, but most instructions simply move some data from one register, or memory location, or an instruction immediate to another register (or memory location). Some of them compute instead of/beyond just moving data, such as adding two things together. These accomplish tiny changes in the state of the processor, and require sequences of instructions to accomplish anything of significance. Still, we need to understand these most primitive operations in order to follow the program.

  2. How are the most basic operations (that we would see in high level languages) performed. All assembly languages use some form of if-goto-label for control structures like loops and if-then-else. The if-goto-label form is some way of saying "if this is true (or false) then change the instruction stream to this other sequence at this other location, but if it is false (or true) then keep doing the current, sequential instruction stream". Conditional branches usually involve a construct such as "if a > b then goto Label;" so all processors can do this but there are a lot of operands involved in such a conditional, so many processors split these into a couple of instructions. (a, b are operands, > is another as there are many different relational operators, and then Label is yet another operand; that's 4 operands, which usually more than can be done in one instruction, so instruction sets split these operations into two or more instructions, so each has only 2 operands or so.)

  3. And yet at a higher level, how do we accomplish control structures like while-loops, if-then-else, for-loops, and computational expressions using these primitives.


In nand2tetris, there are two broad categories of instructions. The ones tagged with @ in assembly language load the A register with an address. How that is used depends then on subsequent instructions. The @ form takes a label as an operand, but that label can be a code label or a data label, and it is up to the program to do something sensible therewith. The ones that don't start with @ are computational, and can either move data between register, add or subtract, and move data from memory to registers or the other way around.

At the most primitive level, a conditional branch is done by loading the label target into the A register, then performing some computational test & branch, that will conditionally transfer control of the instruction stream, by loading the program counter, either with the value in the A register or not!


So, that first two-instruction sequence says: load the A register with the address of R1, then the next instruction says, load D with the value from memory at A. There, D=M means the D register gets the value of M, Memory, where that implicitly means memory at A or memory[A].

Another two instruction sequence: @END... D;JLE says, load the address of label END into A, and then conditionally branch to that instruction sequence, if D is <= 0. So, the processor will conditionally do PC=A (or not).

And the last two-instruction sequence says always jump to label END, which is presumably right there, so the program ends itself with an infinite loop that does nothing, which is a common way to end programs on simple processors.

The usages @x are references to a data cell/location labeled x. M=D means write to memory and D=M means read from memory. So, there is a variable called x, which is sometimes updated and sometimes consulted.

As for the while loop, it is doing something like

if ( x <= 0 ) goto END;

In order to accomplish this conditional test & branch, first the address of data label x is loaded into A, then memory is accessed/read there and loaded into D (D=M); next the address of code label END is loaded into A. So, when the D;JLE executes, D holds a copy of the value in x, which is tested via the JLE, and also A holds the address of END, which is transferred to the PC (PC=A) when the condition holds (that D <= 0).


That kind of conditional branch is possibly part of a while loop as follows:

while ( x > 0 ) {
    <loop-body>
}

would translate into if-goto-label form as follows:

Loop1Top:
    if ( x <= 0 ) goto Loop1End;
    <loop-body>
    goto Loop1Top;
Loop1End:

You can see the the conditions are opposite for the C and the assembly if-goto because their sense/meaning is inverted: in C the loop condition of the while says when to stay in the loop, whereas in assembly we tell the processor when to exit the loop so the opposite condition is tested.

We don't see the rest of the program so this is just informed speculation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM