简体   繁体   English

理解 Hack 汇编语言代码

[英]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.我的老师给了我这个示例代码来学习,我仍然不明白,与汇编语言代码和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:至少有 3 个级别可以理解此类代码:

  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).这些在教程文本中进行了解释,但大多数指令只是将一些数据从一个寄存器或 memory 位置或直接到另一个寄存器(或 memory 位置)的指令移动。 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.这些在处理器的 state 中完成微小的变化,并且需要指令序列来完成任何重要的事情。 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.所有的汇编语言都对循环和 if-then-else 等控制结构使用某种形式的 if-goto-label。 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". if-goto-label 形式是说“如果这是真(或假),则将指令 stream 更改为该其他位置的其他序列,但如果它为假(或真),则继续执行当前,顺序指令流”。 Conditional branches usually involve a construct such as "if a > b then goto Label;"条件分支通常涉及诸如“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.) (a,b 是操作数,> 是另一个,因为有许多不同的关系运算符,然后 Label 是另一个操作数;这是 4 个操作数,通常在一条指令中可以完成的操作不止一个,因此指令集将这些操作分为两个或更多指令,所以每个只有 2 个操作数左右。)

  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.然而,在更高的层次上,我们如何使用这些原语完成诸如 while 循环、if-then-else、for 循环和计算表达式之类的控制结构。


In nand2tetris, there are two broad categories of instructions.在 nand2tetris 中,有两大类指令。 The ones tagged with @ in assembly language load the A register with an address.在汇编语言中用@ 标记的那些会加载带有地址的A 寄存器。 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. @表格以操作数为label,但该ZD304BA20E96D874115888888888888880E34Z可以是代码ZD304BA20EBA20EE96DBAESTER TOMESTEMENEMENIBER PROPHEN EREMENIBER PROPREMER PROPREMER PROPREMER PROPREMER PROPREMER PROPREMER PROPREMER PROPREMER PROPREMERITYENYENYENYEN88484848484844444444444440404040404040004000400 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.不以@ 开头的那些是计算性的,可以在寄存器之间移动数据、加法或减法,以及将数据从 memory 移动到寄存器或以其他方式移动。

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!在最原始的级别,通过将 label 目标加载到 A 寄存器中来完成条件分支,然后执行一些计算测试和分支,这将有条件地转移指令 stream 的控制,通过加载程序计数器,或者使用A寄存器与否!


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].所以,前两条指令序列说:用 R1 的地址加载 A 寄存器,然后下一条指令说,用 A 处 memory 的值加载 D。在那里,D=M 表示 D 寄存器获取 M 的值, Memory,其中隐含的意思是 memory 在 A 或内存 [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).另外两条指令序列:@END... D;JLE 说,将 label END 的地址加载到 A 中,然后有条件地跳转到该指令序列,如果 D <= 0。因此,处理器将有条件地执行 PC=A (或不)。

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.最后两条指令序列表示总是跳转到 label END,大概就在那里,所以程序以一个什么都不做的无限循环结束,这是在简单处理器上结束程序的常用方法。

The usages @x are references to a data cell/location labeled x.用法 @x 是对标记为 x 的数据单元格/位置的引用。 M=D means write to memory and D=M means read from memory. M=D 表示写入 memory,D=M 表示从 memory 读取。 So, there is a variable called x, which is sometimes updated and sometimes consulted.因此,有一个名为 x 的变量,它有时会更新,有时会查询。

As for the while loop, it is doing something like至于while循环,它正在做类似的事情

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);为了完成这个条件测试和分支,首先将数据 label x 的地址加载到 A,然后 memory 在那里访问/读取并加载到 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).接下来将代码label END的地址加载到A中。因此,当D;JLE执行时,D保存了x中值的副本,通过JLE进行测试,并且A保存了END的地址,该地址被传输当条件成立时(即 D <= 0)发送到 PC(PC=A)。


That kind of conditional branch is possibly part of a while loop as follows:这种条件分支可能是 while 循环的一部分,如下所示:

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

would translate into if-goto-label form as follows:将转换为 if-goto-label 形式,如下所示:

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.您可以看到 C 和程序集 if-goto 的条件是相反的,因为它们的意义/含义是相反的:在 C 中,while 的循环条件表示何时留在循环中,而在汇编中我们告诉处理器何时停止退出循环,以便测试相反的条件。

We don't see the rest of the program so this is just informed speculation.我们没有看到程序的 rest,所以这只是有根据的推测。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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