mips lw 和 sw 指令中的偏移点是什么?
What is the point of offset in mips lw and sw instructions?
我的老师刚刚讨论了这个话题,但我仍然质疑为什么要使用精确的偏移量。是否借助某种前缀对值进行分类?如果您能以简单的方式解释为什么在这些说明中使用偏移量,我将不胜感激。
偏移量用于多种不同的场景。以下是一些示例:
许多算法自然涉及 A[i+1]
等表达式。编译器将计算 A+i
,并使用偏移量 4 来获得 +1(假设 A
是一个 4 字节元素的数组)。
展开循环后,即使只涉及 A[i]
,展开的部分会引入 A[i+1]
、A[i+2]
等的用法。偏移量对这些用法很有用。
当我们访问基于堆栈的内存时,基址寄存器将成为堆栈指针,寄存器$sp
。这里的偏移量表示要访问哪个堆栈槽,因此对于访问本地基于堆栈的变量非常方便。
堆栈有隐藏的用法(对 C 程序员隐藏),其中涉及保存 $s
寄存器值,return 地址寄存器值 $ra
,并且可能还有在寄存器中传递的参数。这些也可以使用 $sp
作为基址寄存器和适当的偏移量来访问正确的插槽。
不适合寄存器的参数在堆栈上传递,并由调用者(设置参数)和被调用者(访问它们)使用 $sp
作为基数和适当的偏移量进行访问。
可以使用两个指令序列访问全局变量,使用 lui
后跟 lw
或 sw
并带有适当的偏移量。 lui
指令构成高 16 位,lw
或 sw
指令提供低 16 位。这样就可以构成一个32位的地址,可以访问地址space.
任意位置的全局变量
对象有字段,访问字段是使用指向对象的指针和字段在对象内的偏移量来完成的。因此,在 C 中,p->f1
,其中 f1
的偏移量为 8,将使用加载或存储,其中 p
作为基址寄存器,8 作为偏移量。 p->f2
将使用相同的 p
但不同的偏移量。
综上所述,基数+非零常量的场景比较多。零常量也非常有用,正如您已经知道的 *p
(简单解引用)和 A[i]
(数组索引),因此 MIPS 选择仅提供一种形式的寻址模式。
其他架构提供了多种寻址模式,例如带偏移量和不带偏移量(以及其他)的取消引用,因此对于它们,您选择不带偏移量而不是提供为零的偏移量。然后你可以使用更短的指令,因为没有偏移编码(短指令有利于代码密度,这有利于指令缓存性能)。然而,要利用这一点,您需要一个可变长度指令集和更多编码,MIPS 选择反对这两种编码,以符合其 RISC 理念。
我的老师刚刚讨论了这个话题,但我仍然质疑为什么要使用精确的偏移量。是否借助某种前缀对值进行分类?如果您能以简单的方式解释为什么在这些说明中使用偏移量,我将不胜感激。
偏移量用于多种不同的场景。以下是一些示例:
许多算法自然涉及
A[i+1]
等表达式。编译器将计算A+i
,并使用偏移量 4 来获得 +1(假设A
是一个 4 字节元素的数组)。展开循环后,即使只涉及
A[i]
,展开的部分会引入A[i+1]
、A[i+2]
等的用法。偏移量对这些用法很有用。当我们访问基于堆栈的内存时,基址寄存器将成为堆栈指针,寄存器
$sp
。这里的偏移量表示要访问哪个堆栈槽,因此对于访问本地基于堆栈的变量非常方便。堆栈有隐藏的用法(对 C 程序员隐藏),其中涉及保存
$s
寄存器值,return 地址寄存器值$ra
,并且可能还有在寄存器中传递的参数。这些也可以使用$sp
作为基址寄存器和适当的偏移量来访问正确的插槽。不适合寄存器的参数在堆栈上传递,并由调用者(设置参数)和被调用者(访问它们)使用
$sp
作为基数和适当的偏移量进行访问。可以使用两个指令序列访问全局变量,使用
任意位置的全局变量lui
后跟lw
或sw
并带有适当的偏移量。lui
指令构成高 16 位,lw
或sw
指令提供低 16 位。这样就可以构成一个32位的地址,可以访问地址space.对象有字段,访问字段是使用指向对象的指针和字段在对象内的偏移量来完成的。因此,在 C 中,
p->f1
,其中f1
的偏移量为 8,将使用加载或存储,其中p
作为基址寄存器,8 作为偏移量。p->f2
将使用相同的p
但不同的偏移量。
综上所述,基数+非零常量的场景比较多。零常量也非常有用,正如您已经知道的 *p
(简单解引用)和 A[i]
(数组索引),因此 MIPS 选择仅提供一种形式的寻址模式。
其他架构提供了多种寻址模式,例如带偏移量和不带偏移量(以及其他)的取消引用,因此对于它们,您选择不带偏移量而不是提供为零的偏移量。然后你可以使用更短的指令,因为没有偏移编码(短指令有利于代码密度,这有利于指令缓存性能)。然而,要利用这一点,您需要一个可变长度指令集和更多编码,MIPS 选择反对这两种编码,以符合其 RISC 理念。