在 MIPS 中从内存加载 bytes/halfwords

Load bytes/halfwords from memory in MIPS

我被要求使用 .byte 和 .word 指令创建一个数据段,以将值 0x01、0x02、0x03、0x04 存储为字节,将值 0x12345678 存储为字。我的代码是:

.data
    b1: .byte 0x01
    b2: .byte 0x02
    b3: .byte 0x03
    b4: .byte 0x04
    w1: .word 0x12345678

然后我想使用lbu、lhu和lw分别加载值:0x01、0x0201和0x12345678到$t0、$t1、$t2。

我为此所做的是:

    lbu $t0,b1  #this works
    lhu $t1,0(b2)   #this doesn't work, gets an error
    lw $t2,w1   #also works

我的错误是inst/data 中的异常和未对齐的地址提取:0x10010001。 如何加载超过 1 个字节作为半字?我在数据段中的变量声明错误吗?我可能想要这样的东西吗:

byte_array: .byte 0x01,0x02

谢谢大家的帮助。

您正在尝试加载声明为 .byte 的半字 (lhu)。这是大小不匹配,这会导致您收到错误。

但是处理器不关心大小不匹配,而是对齐。所以,如果你想加载一个半字(两个字节),它们必须从偶数字节边界开始,这不是你的数据设置的情况。

lhu $t0, b1 会起作用,lhu $t0,b3lhu $t0,w1 也会起作用,因为这些数据位于偶数地址。但是,b2b4 位于奇数地址。

C 编译器不会让您首先执行大小不匹配的加载,如果没有一些严重的转换,这会让您回到 MIPS 上的这些未对齐错误。此外,x86 处理器将允许未对齐的访问,但在某些情况下,它们会比对齐的等效项慢。

因为未对齐的访问需要更多的硬件,而且编译器通常可以使用他们的类型系统来避免这些问题,所以一些设计选择放弃额外的硬件,MIPS 就是其中之一。

您还可以通过插入填充来改变对齐方式——在 b1b2 之间插入一个额外的字节会改变 b2 的对齐方式,从而允许加载 b2b3 使用 lhu。因为 w1 被声明为 .word 汇编器知道它需要字对齐,所以在 b1b3 之间插入一个字节将导致 w1需要 3 个字节的附加对齐填充(由于使用了 .word 数据声明,汇编程序将提供)。

当你使用这种大小不匹配的时候,也会有字节顺序的问题。 MIPS 模拟器将使用与底层处理器相同的字节顺序,因此在加载 2 个字节时通常会看到小字节序行为。如果你声明两个 .bytes 而不是使用一个 .half 你将不得不选择一个字节顺序。