如何获取数组的地址并将其保存到汇编中的寄存器中?

时间:2017-12-09 16:05:17

标签: arrays assembly mips memory-address cpu-registers

我想在寄存器中保存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

1 个答案:

答案 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)是有意义的,这样它们就可以并行执行,而不是在第一个存储执行之前等待超过必要的时间。

此外,这可以说更具人性化,因为价值和地址是一致的。