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

How to get the address of an array and save it to a register in assembly?

我想将 A[ ] 的内存地址保存在一个寄存器中,比如 $a0 因为即使我可以在程序的任何范围内访问 A,我也会将其作为参数传递给过程。

在代码中,我使用 sb 而不是 sw 的原因是当我 assemble 它时存在对齐问题。

当我说 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

使用la伪指令。 la $t0, A.

如果 A 不适合 16 位,这将 assemble 到像
这样的序列 lui $t0, high16(A); ori $t0, $zero, low16(A)。参见 this basic MIPS instruction-set reference for LUI。您的 assembler 可能会使用 addui 而不是 ori;我认为一些 assemble 用户有一个选项可以选择 li / la 伪指令。

还有一个 li 伪指令(用于立即加载)用于数字常量而不是地址,但它的工作原理相同。


对于对齐问题,请尝试确保 A 的地址是字对齐的。我原以为这会自动发生,但也许您在之前发布的代码 .data 中遗漏了一个 .asciz 字符串常量?无论如何,要么将 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

你不需要每次都使用不同的寄存器,虽然我猜想没有寄存器重命名 a classic-RISC pipeline might stall for a Write-After-Read hazard (WAR)li 试图在前一个 [=31] 之前写 t0 =] 读过它。在超标量 CPU 上,混合不同的指令类型(ALU addui 和内存 sw)是有意义的,这样它们就可以并行执行,而不是在第一个存储执行之前可能等待更长的时间.

此外,这可以说更易读,因为值和地址放在一起。