MIPS汇编,lui 0x1001

时间:2016-12-18 13:17:37

标签: assembly mips mars-simulator

我有一项任务,我必须解释有关以下MIPS汇编代码的一些内容:

.data
x: .word 4711
y: .word 10
z: .word 0x0A91
e: .word 0

.text
.globl main
main:
lw $2, x
lw $3, y
lw $4, z
add $2, $2, $3
sub $3, $2, $4
sw $3, e
li $2, 10
syscall

第一条指令lw $2, x在组装时分为两条指令。说明为lui $1, 0x00001001,后跟lw $2, 0x00000000($1)。我知道lui将十六进制值1001移动到寄存器的上半部分,此时存储在$ 1中的值是0x10010000,但我不明白1001的来源和第二条指令的含义。我真的会在这个主题上找到任何帮助。我正在使用MARS来组装和运行这个程序。

1 个答案:

答案 0 :(得分:2)

MIPS指令长度为32位,程序使用的地址也是如此 这意味着lw指令无法将完整的32位地址指定为立即数。 简而言之,指令lw $t, var无效(预计极少数情况下)。

实际上,它的编码是

lw $t, offset($s)
1000 11ss ssst tttt iiii iiii iiii iiii

i 位表示只有16位用于指定地址(并且必须始终指定基址寄存器,最终可以使用$zero寄存器)。< / p>

所以汇编程序就是这样做的:无论何时使用lw $t, var,它都会将该指令汇编成两个指令,一个将地址的高16位加载到$at的指令和lw使用$at作为基址寄存器,地址的低16位作为偏移量。

lui $at, ADDR_H            #ADDR_H is ADDR >> 16
lw $t, ADDR_L($at)         #ADDR_L is ADDR & 0xffff

请注意,由于lw$at + ADDR_L 读取,因此使用的最终地址为 ADDR_H &lt;&lt; 16 + ADDR_L = ADDR 。正如所料。

这里有微妙之处,由Mike Spivey指出(非常感谢他),见下文

这种没有直接映射到ISA的指令称为伪指令$at寄存器保留给汇编程序,完全用于实现它们。

在MARS中,您可以通过取消选中设置&gt;来停用伪指令。允许扩展(伪)指令和格式 虽然没有伪指令的编程会很快变得烦人,但至少要做一次,以完全理解MIPS架构。

Mike Spivey正确地注意到16位偏移立即数是符号扩展,然后才被添加到基址寄存器。
这需要更正我称为ADDR_H的值,以防ADDR_L在被解释为16位二进制补码数时变为负值。
如果结果为真,则ADDR_H必须递增 ADDR_H的通用公式可以更正为ADDR_H = ADDR >> 16 + ADDR[15],其中ADDR[15]表示ADDR的第15位的值(ADDR_L的符号位。< / p>