【问题标题】:Error #5: Unaligned word memory reference错误 #5:未对齐的字内存引用
【发布时间】:2017-11-25 02:26:45
【问题描述】:

我试图在使用 MIPS 的 Dijkstra 算法的实现中构建一个整数数组来表示边(源索引 | 目标索引 | 权重)。

在使用 rsim 运行时,我收到“未对齐的字内存引用”错误。我想我可能误解了内存对齐指的是什么。我的 .data 在下面

.data
.align 4

enterNode:          .asciiz "Enter the number of nodes: "
enterEdges:         .asciiz "Enter the number of edges: "
enterSource:        .asciiz "Enter source: "
enterDestination:   .asciiz "Enter destination: "
enterWeight:        .asciiz "Enter weight: "
newLine:            .asciiz "\n"
min_nodes:          .word 1
max_nodes:          .word 20
error1:             .asciiz "Invalid number of nodes. Must be between 1 and 20.\n"
error2:             .asciiz "Invalid number of edges. Must be between 0 and 400.\n"
edgeArr:            .space 4800
    # source | destination | weight
input:              .space 5

在 .text 中,我正在循环获取边数以将数据输入到数组中,但似乎我引用或计算地址的方式不正确。

addi    $t0, $zero, 0                   # Edge counter
la      $t1, edgeArr
addi    $t2, $zero, 0

loop:
    # Source
    addi    $v0, $zero, PRINT_STRING    # Print user prompt
    la      $a0, enterSource
    syscall
    addi    $v0, $zero, READ_INT        # Take user input
    syscall
    add     $t3, $t2, $t2               # Calculate address in array
    add     $t3, $t3, $t3
    add     $t3, $t1, $t3
    sw      $v0, ($t3)
    addi    $t2, $t2, 1

    # ...destination and weight are effectively identical to source...

    # Loop condition
    addi    $t0, $t0, 1
    slt     $t4, $t0, $s1
    bne     $t4, $zero, loop

我已经查看了几个类似的问题,但它们似乎并没有完全解决我所误解的部分,我真的可以从一双新的眼睛中受益。

【问题讨论】:

    标签: assembly mips memory-alignment mars-simulator


    【解决方案1】:

    .align 4.space 指令之间有一些字符串。 (.word implicitly aligns by 4 in classic MIPS assemblers like MARS,但.space 没有。)

    .align 4 填充以使当前位置成为2^4 = 16 的倍数。 (您可能希望 .align 2 获得 1字符串的总大小不是 4 的倍数,因此您的 .space 指令不在字对齐的内存地址。

    通过先放置字对齐的对象,然后是奇数长度的数据来解决此问题。

    .data
    .align 4
    min_nodes:          .word 1
    max_nodes:          .word 20
    
    edgeArr:            .space 4800
        # source | destination | weight
    input:              .space 5              # 5 bytes??
    
    
    enterNode:          .asciiz "Enter the number of nodes: "
    enterEdges:         .asciiz "Enter the number of edges: "
    enterSource:        .asciiz "Enter source: "
    enterDestination:   .asciiz "Enter destination: "
    enterWeight:        .asciiz "Enter weight: "
    newLine:            .asciiz "\n"
    error1:             .asciiz "Invalid number of nodes. Must be between 1 and 20.\n"
    error2:             .asciiz "Invalid number of edges. Must be between 0 and 400.\n"
    

    如果min_nodes 是构建时常量,请使用.equ 定义它,而不是将其存储在内存中。 (因此您可以将其用作直接常量)

    .equ  min_nodes, 1
    .equ  max_nodes, 20
    
    ...
    li   $t0, min_modes
    

    sltiu $t1, $t0, min_modes 设置$t1=1 如果$t0 < min_nodes(无符号),否则设置为零。顺便说一句,您可以只用一个分支进行范围检查:

    addui  $t1, $t0, -1
    then compare against 19 (unsigned)
    

    小于 1 的值将换成一个大的无符号值(并比较大于 19)。大于 20 的值仍将大于 19。


    您也不需要将字符串常量与读写值混合。如果您的汇编程序支持.rodata.section .rodata,则您的只读字符串将进入可执行文件的文本段,因此它们受到写保护。

    IIRC,MARS 没有。

    【讨论】:

    • 谢谢,这正是我正在寻找的解释。我没有想过我在哪里声明数组。我还将确保更改最小和最大节点。你是对的,因为它们只是常量,这可能是声明它们的更好方法。我不确定汇编器是否支持 .rodata,但我会查看文档。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-07
    • 1970-01-01
    • 2013-10-21
    • 2013-06-27
    • 1970-01-01
    • 2019-06-10
    相关资源
    最近更新 更多