迭代 mips 程序集数组的最简单方法是什么?
What is the simplest way to iterate through a mips assembly array?
我想以最干净的方式复制它
在python
A = [0,0,0,0,0]
i = 0
while(i != 5):
A[i] = 10
i++
也就是说,我想遍历一个数组并将其所有值设置为[10,10,10,10,10]
这是我在 mips 汇编中所做的
.data
array: .word 0:5
.text
main:
li $t1, 0 # i = 0
la $t9, array # $t9 = addr(array)
li $t8, 10 # $t8 = 10
start_loop:
beq $t1, 5, end_loop # if i == 5 jump to end loop
sll $t2, $t1, 2 # $t2 = i x 4
add $t2, $t9, $t2 # $t3 = addr(array[i])
sw $t8, 0($t2) # array[i] = $t8
addi $t1, $t1, 1 # i = i + 1
j start_loop
end_loop:
li $v0, 10 # end program
syscall
我觉得我用了很多寄存器,这不是最干净的方法。任何帮助表示赞赏
(还要确保使用循环,我可以在没有循环的情况下对其进行硬编码,但我只是想找出其他使用循环的方法)
.data
array: .word 0:5
array_end:
.text
main:
la $t2, array
addiu $t1, $t2, 20 # one-past-end address for loop condition
# or la $t1, array_end to avoid hard-coding length
li $v0, 10
start_loop: # do{
sw $v0, 0($t2) # array[i] = $t8
addiu $t2,$t2,4 #increment pointer after
beq $t1, $t2, start_loop # }while(p != endp);
#end_loop:
#li $v0, 10 # exit call number happens to be the same value we wanted to store
syscall # exit
改动(在 Peter 的帮助下)
所以要做的第一件事就是删除 i 变量。相反,我们可以将 $t2
的地址(指向数组的指针)与我们在循环外设置的结束指针 ($t1
) 进行比较,这将告诉我们完成了。如果不是,则分支到 start_loop。
指针递增而不是每次都重做索引在像 MIPS 这样没有索引寻址模式的机器上特别好。
在循环底部使用条件分支循环意味着您不需要 j
指令,并且对于所有(?)ISA 的汇编语言来说都是惯用的(例如 ) .当你知道循环肯定会 运行 至少一次时,它特别好,所以你不需要在循环之前的分支来跳过它。
.data
array: .word 0:5
.text
main:
li $t1, 0 #initialize i = 0
la $t2, array #load address of array[0]
li $t3, 10 #save 10 in a register
loop:
beq $t1, 5, end #if i == 5, end
sw $t3, ($t2) #array[i] = 10
add $t2, $t2, 4 #increment array address pointer by 4
add $t1, $t1, 1 #i = i + 1
j loop
end:
li $v0, 10
syscall
我想以最干净的方式复制它
在python
A = [0,0,0,0,0]
i = 0
while(i != 5):
A[i] = 10
i++
也就是说,我想遍历一个数组并将其所有值设置为[10,10,10,10,10]
这是我在 mips 汇编中所做的
.data
array: .word 0:5
.text
main:
li $t1, 0 # i = 0
la $t9, array # $t9 = addr(array)
li $t8, 10 # $t8 = 10
start_loop:
beq $t1, 5, end_loop # if i == 5 jump to end loop
sll $t2, $t1, 2 # $t2 = i x 4
add $t2, $t9, $t2 # $t3 = addr(array[i])
sw $t8, 0($t2) # array[i] = $t8
addi $t1, $t1, 1 # i = i + 1
j start_loop
end_loop:
li $v0, 10 # end program
syscall
我觉得我用了很多寄存器,这不是最干净的方法。任何帮助表示赞赏
(还要确保使用循环,我可以在没有循环的情况下对其进行硬编码,但我只是想找出其他使用循环的方法)
.data
array: .word 0:5
array_end:
.text
main:
la $t2, array
addiu $t1, $t2, 20 # one-past-end address for loop condition
# or la $t1, array_end to avoid hard-coding length
li $v0, 10
start_loop: # do{
sw $v0, 0($t2) # array[i] = $t8
addiu $t2,$t2,4 #increment pointer after
beq $t1, $t2, start_loop # }while(p != endp);
#end_loop:
#li $v0, 10 # exit call number happens to be the same value we wanted to store
syscall # exit
改动(在 Peter 的帮助下)
所以要做的第一件事就是删除 i 变量。相反,我们可以将 $t2
的地址(指向数组的指针)与我们在循环外设置的结束指针 ($t1
) 进行比较,这将告诉我们完成了。如果不是,则分支到 start_loop。
指针递增而不是每次都重做索引在像 MIPS 这样没有索引寻址模式的机器上特别好。
在循环底部使用条件分支循环意味着您不需要 j
指令,并且对于所有(?)ISA 的汇编语言来说都是惯用的(例如
.data
array: .word 0:5
.text
main:
li $t1, 0 #initialize i = 0
la $t2, array #load address of array[0]
li $t3, 10 #save 10 in a register
loop:
beq $t1, 5, end #if i == 5, end
sw $t3, ($t2) #array[i] = 10
add $t2, $t2, 4 #increment array address pointer by 4
add $t1, $t1, 1 #i = i + 1
j loop
end:
li $v0, 10
syscall