【问题标题】:How to get the address of an array and save it to a register in assembly?如何获取数组的地址并将其保存到程序集中的寄存器中?
【发布时间】:2017-12-09 16:05:16
【问题描述】:

我想将 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

【问题讨论】:

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


    【解决方案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 的地址是字对齐的。我原以为这会自动发生,但也许您在发布的代码中早先在.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 可能会在 li 尝试在之前的 sw 之前写入 t0 时停止 Write-After-Read hazard (WAR)阅读。在超标量 CPU 上,混合不同的指令类型(ALU addui 和内存 sw)是有意义的,这样它们就可以并行执行,而不是在第一次存储执行之前等待比必要的时间更长。

    此外,这可以说更易于人类阅读,因为值和地址是一起的。

    【讨论】:

    • 感谢您花时间解决我的问题。你真好。
    • 我在到达 A 时遇到了问题。假设我将 A 的地址保存在 $a0 中,并希望到达 A($a1)。当我想加载那个词时,$a0($a1) 不起作用。如何使用 $a0 访问元素?
    • @M.Kaan:MIPS 只有一种寻址模式:寄存器 + imm32。如果需要 2 寄存器地址,则需要将单独的 addu 指令放入临时寄存器。
    猜你喜欢
    • 2019-12-26
    • 1970-01-01
    • 2021-08-22
    • 1970-01-01
    • 1970-01-01
    • 2021-12-30
    • 1970-01-01
    • 2021-07-25
    • 2013-03-24
    相关资源
    最近更新 更多