我想在寄存器中保存A []的内存地址,比如$ a0,因为即使我可以在程序的任何范围内达到A,我都会将此作为参数传递给程序。
在代码中,我使用sb
代替sw
的原因是我在组装它时存在一个对齐问题。
当我说lb $a0, A
时,它会将4
存储到$a0
,这不是地址的值。
.data
A: .space 16
.globl main
main:
# Initialize values in the array
addi $s0, $zero, 4
addi $s1, $zero, 8
addi $s2, $zero, 3
addi $s3, $zero, 5
# This $t0 is just used for indexing while inserting to A
addi $t0, $zero, 0
sb $s0, A($t0)
addi $t0, $t0, 4
sb $s1, A($t0)
addi $t0, $t0, 4
sb $s2, A($t0)
addi $t0, $t0, 4
sb $s3, A($t0)
li $t0, 0
答案 0 :(得分:1)
使用la
伪指令。 la $t0, A
。强>
如果A
不适合16位,则会汇编为类似
的序列
lui $t0, high16(A)
; ori $t0, $zero, low16(A)
即可。见this basic MIPS instruction-set reference for LUI。汇编程序可以使用addui
代替ori
;我认为一些汇编程序可以选择li
/ la
伪指令。
还有一个li
伪指令(用于加载立即)用于数字常量而不是地址,但它的工作方式相同。
对于对齐问题,请尝试确保A
的地址是字对齐的。我原本以为这会自动发生,但是你可能会在.asciz
之前从你发布的代码中遗漏一个.data
字符串常量?无论如何,要么先将A
放在非多个4大小的对象之前,要么使用.align
指令填充下一个4的倍数。
.data
.align 4 # align by 4 bytes.
A: .space 16
如果A
的地址适合16位,则不需要它或寄存器中的偏移量,只需使用sb $s0, A+4($zero)
,依此类推。 (但是如果你使用的是sb / lb,那么为什么仍然会在元素之间偏移4个字节?为什么不把它作为一个4字节长的4字节数组呢?)
.globl main
main:
# Initialize values in the array
li $t0, 4
sw $t0, A($zero)
addui $t0, $zero, 8 # doing it manually without an LI pseudo-instruction
sw $t0, A+4($zero)
li $t0, 3
sw $t0, A+8($zero)
li $t0, 5
sw $t0, A+12($zero)
#li $t0, 0
您不需要每次都使用不同的寄存器,但我想如果li
尝试写t0
时没有注册重命名a classic-RISC pipeline可能会停止Write-After-Read hazard (WAR)在上一个sw
阅读之前。在超标量CPU上,混合使用不同的指令类型(ALU addui
和内存sw
)是有意义的,这样它们就可以并行执行,而不是在第一个存储执行之前等待超过必要的时间。
此外,这可以说更具人性化,因为价值和地址是一致的。