错误 #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 没有。
我试图在使用 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 没有。