MIPS 程序集,lui 0x1001
MIPS Assembly, lui 0x1001
我有一个作业,我必须在其中解释有关以下 MIPS 汇编代码的一些事情:
.data
x: .word 4711
y: .word 10
z: .word 0x0A91
e: .word 0
.text
.globl main
main:
lw , x
lw , y
lw , z
add , ,
sub , ,
sw , e
li , 10
syscall
第一条指令lw , x
在assembled时被分成两条指令。指令是 lui , 0x00001001
后跟 lw , 0x00000000()
。我明白lui将十六进制值1001移到寄存器的上半部分,此时$1中存储的值为0x10010000,但我完全不明白1001是从哪里来的,第二条指令是什么意思。我真的很感激任何关于 subject.I 的帮助,我正在使用 MARS 来 assemble 和 运行 这个程序。
MIPS 指令是 32 位长,程序使用的地址也是如此。
这意味着 lw
指令无法将完整的 32 位地址指定为立即数。
简单地说,指令 lw $t, var
无效(预计极少数情况)。
其实它的编码是
lw $t, offset($s)
1000 11ss ssst tttt iiii iiii iiii iiii
其中 i 位表示只有 16 位用于指定地址(并且必须始终指定基址寄存器,最终 $zero
寄存器可以被使用)。
所以汇编器做了这个把戏:每当你使用 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 << 16 + ADDR_L = ADDR。不出所料。
这里有微妙之处,指出(非常感谢他),见下文
这种不直接映射到ISA的指令被称为伪指令。
$at
寄存器是为汇编程序保留的,正是为了实现它们。
在 MARS 中,您可以通过取消选中 设置 > 允许扩展(伪)指令和格式来禁用伪指令。
虽然没有伪指令的编程会很快变得烦人,但至少值得做一次,以充分理解 MIPS 体系结构。
正确地注意到 16 位偏移立即数在添加到基址寄存器之前是 符号扩展 。
这需要更正我称为 ADDR_H
的值,以防 ADDR_L
在被解释为 16 位二进制补码时结果为负数。
如果结果为真,则必须增加 ADDR_H
。
ADDR_H
的一般公式可以更正为 ADDR_H = ADDR >> 16 + ADDR[15]
其中 ADDR[15]
表示 ADDR
的第 15 位(即 ADDR_L
的符号位)的值。
我有一个作业,我必须在其中解释有关以下 MIPS 汇编代码的一些事情:
.data
x: .word 4711
y: .word 10
z: .word 0x0A91
e: .word 0
.text
.globl main
main:
lw , x
lw , y
lw , z
add , ,
sub , ,
sw , e
li , 10
syscall
第一条指令lw , x
在assembled时被分成两条指令。指令是 lui , 0x00001001
后跟 lw , 0x00000000()
。我明白lui将十六进制值1001移到寄存器的上半部分,此时$1中存储的值为0x10010000,但我完全不明白1001是从哪里来的,第二条指令是什么意思。我真的很感激任何关于 subject.I 的帮助,我正在使用 MARS 来 assemble 和 运行 这个程序。
MIPS 指令是 32 位长,程序使用的地址也是如此。
这意味着 lw
指令无法将完整的 32 位地址指定为立即数。
简单地说,指令 lw $t, var
无效(预计极少数情况)。
其实它的编码是
lw $t, offset($s)
1000 11ss ssst tttt iiii iiii iiii iiii
其中 i 位表示只有 16 位用于指定地址(并且必须始终指定基址寄存器,最终 $zero
寄存器可以被使用)。
所以汇编器做了这个把戏:每当你使用 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 << 16 + ADDR_L = ADDR。不出所料。
这里有微妙之处,
这种不直接映射到ISA的指令被称为伪指令。
$at
寄存器是为汇编程序保留的,正是为了实现它们。
在 MARS 中,您可以通过取消选中 设置 > 允许扩展(伪)指令和格式来禁用伪指令。
虽然没有伪指令的编程会很快变得烦人,但至少值得做一次,以充分理解 MIPS 体系结构。
这需要更正我称为 ADDR_H
的值,以防 ADDR_L
在被解释为 16 位二进制补码时结果为负数。
如果结果为真,则必须增加 ADDR_H
。
ADDR_H
的一般公式可以更正为 ADDR_H = ADDR >> 16 + ADDR[15]
其中 ADDR[15]
表示 ADDR
的第 15 位(即 ADDR_L
的符号位)的值。