首页 > 解决方案 > 如何培养对 LC-3 汇编代码的直觉?

问题描述

我读到了 LC-3 是如何工作的,但我一生都无法弄清楚如何在 LC-3 程序集中进行编码。我的目标是能够编写简单的程序,例如生成斐波那契数或对数组进行排序。

有人可以指点我的资源来学习这个吗?我精通 Python 和 Java,所以这些问题背后的基本逻辑对我来说很清楚。

标签: assemblylc3lc3-trap

解决方案


学习汇编语言有几个方面,它是处理器机器代码的人类可读版本。

基本上其他语言处于逻辑级别,而机器代码非常处于物理级别

  • 一方面,这尤其体现在存储概念上的差异:

    • 逻辑变量与物理 CPU 寄存器和内存
    • 逻辑变量是动态的,CPU 寄存器和内存是固定的、永久的
    • 具有类型的变量与具有位的物理存储

    因此,当我们编写汇编语言时,我们翻译了我们的伪代码:具有许多生命周期有限的类型变量的逻辑代码,部分是通过将逻辑变量映射到固定的物理资源上。变量通常比 CPU 寄存器多,尤其是当某些寄存器具有专用用途时,例如堆栈或返回地址。

  • 另一方面,今天的其他语言通常采用结构化编程,而在汇编语言/机器代码中,我们有 if-goto-label。

    所有结构化语句在 if-goto-label 中都有翻译。每个翻译都是将结构化形式的模式转换为 if-goto-label 形式的模式。正确地遵循模式,您将重现伪代码的控制流——在这里很容易走捷径并犯令人困惑的错误,因此我鼓励在这里采用有条不紊的方法。

  • 其他语言有丰富的表达方式:有许多优先级的运算符,以及使用()'s 的复杂程度。机器代码的指令(通常)最多需要 3 个操作数。

  • 函数调用、堆栈帧、参数传递、返回值是一个相当深入的主题,函数序言和结语。

    • 参数需要由调用者放置到已知位置,并由被调用者从这些位置找到
    • 固定的物理寄存器需要在调用者和被调用者之间共享,因此有一个协议可以进行共享。寄存器要么是调用保留的,要么是调用破坏的——每个组都适用于不同的场景,并且有自己的规则/要求才能正常工作。
    • 在汇编语言中可以有一个显式的调用堆栈和堆栈指针,这是我们在 C 代码中看不到的。
    • 可以有一个显式的返回地址,它应该被认为是一个参数,被调用者用来返回给正确的调用者(因为它可以动态地不同)。
    • 返回值由被调用者放置到已知位置,并在返回时由调用者找到。
    • 保存调用保留的寄存器、局部变量存储(例如用于数组)、参数(包括返回地址)和局部变量可以在函数调用中存在——所有这些都需要内存存储,通常以在堆栈上分配一些空间的形式(虽然有时在 LC-3 上这些是作为全局变量完成的,这意味着不支持递归)。如果堆栈空间用于其中任何一个,则该空间称为堆栈帧。
      • 堆栈空间在函数序言中分配并在函数尾声中释放——这些是函数体之前和之后的函数代码部分(它们在每次函数调用时只执行一次,即使整个函数体也不会成为循环的一部分函数是一个循环)。
    • 通过查找您正在使用的“调​​用约定”来查看更多信息,它将描述寄存器共享组、专用寄存器(例如堆栈指针)以及参数和返回值位置。
    • 分析逻辑变量是否“在调用中有效”有助于选择适当的 CPU 寄存器,并告诉我们是否需要在序言中保存该寄存器并在结尾中恢复它。

有关详细信息,请参阅以下一些资源:


推荐阅读