简体   繁体   English

如何培养对 LC-3 汇编代码的直觉?

[英]How to develop an intuition to code in LC-3 Assembly?

I read about how LC-3 works, but I can't for the life of me figure out how to code in LC-3 assembly.我读到了 LC-3 是如何工作的,但我一生都无法弄清楚如何在 LC-3 程序集中进行编码。 My goal is to be able to write simple programs like generating Fibonacci numbers or sorting an array.我的目标是能够编写简单的程序,例如生成斐波那契数或对数组进行排序。

Can someone point to me to resources to learn this?有人可以指点我的资源来学习这个吗? I'm fluent in Python and Java, so the underlying logic behind those problems is clear to me.我精通 Python 和 Java,所以这些问题背后的基本逻辑对我来说很清楚。

There are several aspects to learning assembly language, which is the human readable version of the machine code of the processor.学习汇编语言有几个方面,它是处理器机器代码的人类可读版本。

Basically other languages are at a logical level, whereas machine code is very much at a physical level基本上其他语言处于逻辑级别,而机器代码非常处于物理级别

  • For one, this goes particularly to the difference in the notions of storage:一方面,这尤其体现在存储概念上的差异:

    • Variables, which are logical vs. CPU registers and memory which are physical变量,它们是逻辑与 CPU 寄存器和 memory 是物理的
    • Logical variables are dynamic, CPU registers and memory are fixed, permanent逻辑变量是动态的,CPU寄存器和memory是固定的,永久的
    • Variables, which have types vs. physical storage having bits具有类型的变量与具有位的物理存储

    So, when we write assembly language, we translate our pseudo code: logical code with lots of typed variables of limited lifetime, in part by mapping logical variables onto the fixed physical resources.因此,当我们编写汇编语言时,我们翻译了我们的伪代码:具有许多生命周期有限的类型变量的逻辑代码,部分是通过将逻辑变量映射到固定的物理资源上。 There are often more variables than CPU registers, especially when some of the registers have dedicated purpose, like stack or return address.变量通常比 CPU 寄存器多,尤其是当某些寄存器具有专用用途时,例如堆栈或返回地址。

  • For another, today's other languages generally employ structured programming, whereas in assembly language/machine code we have if-goto-label.另一方面,今天的其他语言通常采用结构化编程,而在汇编语言/机器代码中,我们有 if-goto-label。

    All structured statements have translation in if-goto-label.所有结构化语句在 if-goto-label 中都有翻译。 Each translation is a transformation of a pattern in structured form to a pattern in if-goto-label form.每个翻译都是将结构化形式的模式转换为 if-goto-label 形式的模式。 Follow the patterns properly and you'll reproduce the control flow of your pseudo code — very easy to take short cuts here and make confusing mistakes, so I encourage a methodical approach here.正确地遵循模式,您将重现伪代码的控制流——在这里很容易走捷径并犯令人困惑的错误,因此我鼓励在这里采用有条不紊的方法。

  • Other languages have rich expressions: having operators of many levels of precedence, and as complex as you like using () 's.其他语言有丰富的表达式:具有许多优先级的运算符,并且可以使用()的复杂性。 Machine code has instructions that take (usually) at most 3 operands.机器代码的指令(通常)最多需要 3 个操作数。

  • Function calls, stack frames, parameter passing, return values are a fairly deep subject, function prologue & epilogue. Function 调用、堆栈帧、参数传递、返回值是一个相当深的主题,function 序言和结语。

    • Parameters need to be placed into known locations by the caller and found from those locations by the callee参数需要由调用者放置到已知位置,并由被调用者从这些位置找到
    • The fixed physical registers need to be shared between caller and callee, so there is a protocol for doing that sharing.固定的物理寄存器需要在调用者和被调用者之间共享,因此有一个协议可以进行共享。 Registers are either call preserved or call clobbered — each group is appropriate for a different scenario, and has its own rules/requirements in order to work properly.寄存器要么是调用保留的,要么是调用破坏的——每个组都适用于不同的场景,并且有自己的规则/要求才能正常工作。
    • There can be an explicit call stack with stack pointer in assembly language that we don't see in C code.在汇编语言中可以有一个带有堆栈指针的显式调用堆栈,这是我们在 C 代码中看不到的。
    • There can be an explicit return address, which should be thought of as a parameter, that the callee uses to return to the proper caller (as that can be different dynamically).可以有一个显式的返回地址,它应该被认为是一个参数,被调用者用来返回给正确的调用者(因为它可以动态地不同)。
    • Return values are placed into known locations by the callee and found there by the caller upon return.返回值由被调用者放置到已知位置,并在返回时由调用者找到。
    • Saving call-preserved registers, local variable storage eg for arrays, and parameters (including the return address) and local variables can be live across a function call — all these things need memory storage, usually in the form of some space allocated on the stack (though sometimes on LC-3 these are done as global variables, which means recursion is not supported).保存调用保留的寄存器,局部变量存储,例如 arrays,参数(包括返回地址)和局部变量可以在 function 调用中存活——所有这些东西都需要 ZCD69B4957F06CD818D7BF3D61980 的堆栈空间,通常以存储空间的形式(虽然有时在 LC-3 上这些是作为全局变量完成的,这意味着不支持递归)。 If stack space is used for any of these, that space is called a stack frame.如果堆栈空间用于其中任何一个,则该空间称为堆栈帧。
      • Stack space is allocated in function prologue and released in function epilogue — these are sections of the function code that precede and follow the function body (they are executed only once per function invocation, they are never part of loops even if the entire body of the function is a loop). Stack space is allocated in function prologue and released in function epilogue — these are sections of the function code that precede and follow the function body (they are executed only once per function invocation, they are never part of loops even if the entire body of the function 是一个循环)。
    • See more information by looking for the "calling convention" you're using, which will describe the register sharing groups, dedicated registers (eg stack pointer), and parameter and return value locations.通过查找您正在使用的“调用约定”来查看更多信息,它将描述寄存器共享组、专用寄存器(例如堆栈指针)以及参数和返回值位置。
    • An analysis of whether a logical variable is "live across a call" helps to choose the an appropriate CPU register and tells us whether we need to save that register in prologue and restore it in epilogue.分析逻辑变量是否“在调用中有效”有助于选择适当的 CPU 寄存器,并告诉我们是否需要在序言中保存该寄存器并在结尾中恢复它。

For more information, see some of following resources:有关详细信息,请参阅以下一些资源:

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

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