错误 #5:未对齐的字内存引用

Error #5: Unaligned word memory reference

我试图在使用 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

我看过几个类似的问题,但它们似乎并没有完全解决我误解的部分,我真的可以从一双新的眼睛来看这个问题。

您在 .align 4.space 指令之间有一些字符串。 (,但 .space 没有。)

.align 4 填充使当前位置成为 2^4 = 16 的倍数。 (您可能希望 .align 2 获得 1<<2 = 4 字节对齐)。 字符串的总大小不是 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 没有。