汇编中的伪指令和软件抽象
Pseudoinstuctions and software abstractions in Assembly
这更像是一个一般性的理论问题。
我正在学习一些汇编语言,并且注意到一些软件,例如用于 MIPS 的 MARS,
实现架构的真实指令集中不存在的抽象,这些指令似乎被称为伪指令,其中的例子是li
,以及其他舒适的抽象,如整洁的数组创建等
我的问题是:
- 如果我想成为一名专业的汇编程序员,我有什么理由要避免这些令人费解的抽象吗?
- 专业的汇编编程是否缺乏这种抽象?
我有点怀疑它只是为了教育目的而存在,但还没有找到任何这方面的信息。
作为一名“专业的汇编程序员”,如果不使用易于阅读的 move
伪指令,您可能会疏忽使用晦涩的三操作数形式,这些形式可以将值从一个寄存器移动到另一个寄存器使用晦涩的 3 操作数形式将立即数移入寄存器,而不是易于阅读的 li
伪指令。
避免使用伪指令的主要原因是您的导师说您不能使用它们。
但是,在使用它们时,我们应该了解它们,它们可能会导致意想不到的低效率。许多伪指令(但不是全部)扩展为 2 或 3 条真实的硬件指令。使用它们隐藏了优化的机会。
例如,比较寄存器和立即数(硬件不直接支持)的分支有一个扩展,需要将一个立即数值加载到一个寄存器中,以便使用该寄存器来寄存器比较。如果您知道这一点,那么在循环中执行此操作,我们可能会将立即数加载到寄存器中 outside/before 循环以保存该指令及其循环内的循环。
此外,一般来说,MIPS 汇编程序支持使用 CPU 寄存器 $at
扩展和互连的伪指令。因此,汇编程序员被警告不要使用这个寄存器;调用约定将 $at
描述为“为汇编器保留”。但是,CPU寄存器是宝贵的资源,这种专门预留是一种浪费。 (请注意,编译器不受此保留约束,可以自由使用 $at
作为暂存寄存器 [call clobbered]。)
RISC V 及其汇编程序已经消除了这个“汇编程序保留”寄存器(将其还给程序员)并且只支持无需汇编程序专用寄存器即可完成的伪指令。虽然仍然支持各种 lw $regtrg, label($regsrc)
形式(尽管它们很丑陋),但类似的 sw
形式并不支持,因为它们需要额外的寄存器! RISC V 还删除了两个 $k
寄存器(为操作系统保留),将它们还给用户模式代码,并且还扩展了调用约定以在寄存器中传递更多参数。这些变化使 RISC V 更有效地使用稀缺资源(CPU 寄存器)。
这更像是一个一般性的理论问题。
我正在学习一些汇编语言,并且注意到一些软件,例如用于 MIPS 的 MARS,
实现架构的真实指令集中不存在的抽象,这些指令似乎被称为伪指令,其中的例子是li
,以及其他舒适的抽象,如整洁的数组创建等
我的问题是:
- 如果我想成为一名专业的汇编程序员,我有什么理由要避免这些令人费解的抽象吗?
- 专业的汇编编程是否缺乏这种抽象?
我有点怀疑它只是为了教育目的而存在,但还没有找到任何这方面的信息。
作为一名“专业的汇编程序员”,如果不使用易于阅读的 move
伪指令,您可能会疏忽使用晦涩的三操作数形式,这些形式可以将值从一个寄存器移动到另一个寄存器使用晦涩的 3 操作数形式将立即数移入寄存器,而不是易于阅读的 li
伪指令。
避免使用伪指令的主要原因是您的导师说您不能使用它们。
但是,在使用它们时,我们应该了解它们,它们可能会导致意想不到的低效率。许多伪指令(但不是全部)扩展为 2 或 3 条真实的硬件指令。使用它们隐藏了优化的机会。
例如,比较寄存器和立即数(硬件不直接支持)的分支有一个扩展,需要将一个立即数值加载到一个寄存器中,以便使用该寄存器来寄存器比较。如果您知道这一点,那么在循环中执行此操作,我们可能会将立即数加载到寄存器中 outside/before 循环以保存该指令及其循环内的循环。
此外,一般来说,MIPS 汇编程序支持使用 CPU 寄存器 $at
扩展和互连的伪指令。因此,汇编程序员被警告不要使用这个寄存器;调用约定将 $at
描述为“为汇编器保留”。但是,CPU寄存器是宝贵的资源,这种专门预留是一种浪费。 (请注意,编译器不受此保留约束,可以自由使用 $at
作为暂存寄存器 [call clobbered]。)
RISC V 及其汇编程序已经消除了这个“汇编程序保留”寄存器(将其还给程序员)并且只支持无需汇编程序专用寄存器即可完成的伪指令。虽然仍然支持各种 lw $regtrg, label($regsrc)
形式(尽管它们很丑陋),但类似的 sw
形式并不支持,因为它们需要额外的寄存器! RISC V 还删除了两个 $k
寄存器(为操作系统保留),将它们还给用户模式代码,并且还扩展了调用约定以在寄存器中传递更多参数。这些变化使 RISC V 更有效地使用稀缺资源(CPU 寄存器)。