我很好奇为什么我们不允许在 MIPS 中使用寄存器作为偏移量。我知道您不能使用寄存器作为偏移量,如下所示:lw $t3, $t1($t4)
;我只是好奇为什么会出现这种情况。
是硬件限制吗?或者只是 ISA 的一部分?
PS:如果您正在寻找替代方法,请参阅 Load Word in MIPS, using register instead of immediate offset from another register 或者查看 C 函数的编译器输出,如 int foo(int *arr, int idx){ return arr[idx]; }
-https://godbolt.org/z/PhxG57ox1
最佳答案
I'm curious as to why we are not allowed to use registers as offsets in MIPS.
我不确定您的意思是“为什么 MIPS 程序集不允许您编写这种形式”还是“为什么底层 ISA 不提供这种形式”。
如果是前者,那么答案是基本 ISA 没有任何提供该功能的机器指令,显然设计者没有决定提供任何 pseudo-instruction这将在幕后实现。2
如果您问为什么 ISA 一开始不提供它,那只是一个设计选择。通过提供更少或更简单的寻址模式,您可以获得以下优势:
- 需要更少的空间来编码一组更有限的可能性,因此您可以为更多操作码、更短指令等节省编码空间。
- 硬件可以更简单,或者更快。例如,在地址计算中允许两个寄存器可能会导致:
- 寄存器文件中需要额外的读取端口1。
- 寄存器文件和 AGU 之间的附加连接,以获取其中的两个寄存器值。
- 需要进行全宽度(32 或 64 位)加法,而不是简单的地址端 + 16 位偏移加法。
- 如果您仍想支持 2 寄存器地址的立即偏移,则需要有一个三输入 ALU(如果不支持,它们的用处就不大)。
- 指令解码和地址生成更加复杂,因为您可能需要支持两条完全不同的地址生成路径。
当然,在某些情况下,所有这些权衡可能会得到很好的返回,可以充分利用 2-reg 寻址和更小或更快的代码,但深受 RISC 哲学启发的原始设计并没有'不包括它。正如彼得指出的那样in the comments ,随后在某些情况下添加了新的寻址模式,尽管显然不是用于加载或存储的通用 2-reg 寻址模式。
Is it a hardware restriction? Or simply just part of the ISA?
这里有一点错误的二分法。当然,这不是硬件限制,因为硬件肯定可以支持这一点,即使是在设计 MIPS 时也是如此。这似乎暗示某些现有硬件有这种限制,因此 MIPS ISA 以某种方式继承了它。我怀疑情况恰恰相反:ISA 是这样定义的,基于对硬件实现可能性的分析,然后它变成了硬件简化,因为 MIPS 硬件不需要支持 MIPS ISA 之外的任何内容。
1 例如,支持需要从 3 个寄存器读取的存储指令。
2 当然值得一问这样的伪指令是否是一个好主意:它可能会扩展为将两个寄存器添加到一个临时寄存器,然后添加一个 lw
结果。这总是存在隐藏“太多”工作的危险。由于这在一定程度上掩盖了将 1:1 映射到硬件负载的真实负载与在幕后进行额外算术的版本之间的差异,因此很容易想象它可能会导致次优决策。
举一个在循环中线性访问两个元素大小相等的数组的经典示例。使用 2-reg 寻址,很自然地将此循环编写为两个 2-reg 访问(每个访问具有不同的基址寄存器和公共(public)偏移寄存器)。偏移维护的唯一“开销”是单个偏移增量。这隐藏了一个事实,即内部需要两个隐藏的添加来支持寻址模式:直接递增每个基数而不使用偏移量会更好。此外,一旦开销清楚,您可以看到展开循环并使用立即偏移可以进一步减少开销。
关于assembly - 为什么MIPS不能在寻址模式下使用两个寄存器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46879095/