如何在循环中访问数组的各个元素?
How can I access the individual elements of an array in a loop?
我需要打印一个数组的单元格,我有一个包含单词 "HELLO_WORLD" 的数组,我设法自己打印一个索引,但我无法打印所有单元格一个,这是代码:
loop:
la $t0, hexdigits # address of the first element
lb $a0, 5($t0) # hexdigits[10] (which is 'A')
li $v0, 11 #system call service
syscall
addi $a0, $a0, 2
li $v0, 11 # I will assume syscall 11 is printchar (most simulators support it)
syscall # issue a system call
j end
是否可以使用指令 lb $a0, $s0($t0) 和一个我可以随时递增的寄存器?而不仅仅是一个数字?
这是我对您所追求的解决方案的最佳尝试。
.data
mystring: .asciiz "HELLO_WORLD" # zero-terminated string
.text
la $t0, mystring # Load the array
li $t1, 0 # Create the loop counter
li $v0, 11 # Syscall code for print character
loop:
add $t2, $t0, $t1 # Load the address for the element at the current index
lb $a0, 0($t2) # Load the value of the array at the current index into $a0
# (For printing)
beqz $a0, exit # If the value at the current index is null, you have
# reached the end of the string, so exit out
syscall # Print the character in $a0 (Syscall code in $v0: 11)
addi $t1, $t1, 1 # Increment the counter
j loop # Jump to the beginning of the loop
exit: # Should be reached once you have hit the end of the string
免责声明:我不懂 MIPS 汇编,我试着尽可能多地了解你的问题。我只能在不支持打印到屏幕(系统调用)的在线模拟器中测试这个程序。 不要只是盲目地粘贴此代码并回复“不,不起作用”。如果有任何问题,请尽量具体,我会尽力解决问题。
编者注:在修复 .asciiz
以确保有一个零终止符之后,即使在 .data 部分中其他非零数据紧随其后,对我来说看起来还不错。
v0=11
/ syscall
保留 $v0
不变,因此 li $v0, 11
可以被提升到循环之外。一些系统调用在 $v0
中放置了一个 return 值,但这个没有。 (MARS syscall docs)
我们可以直接递增 $t1
指针,而不是从 0 开始的计数器。
为了提高效率,我们可以“旋转”循环,使底部有一个 bnez $a0, loop
(不需要 j
),可能是通过剥离第一次迭代:加载并检查循环之前的一个字符,然后以打印为第一件事进入循环。然后递增、加载并检查下一个字符,然后跳出循环或跳到顶部打印它。
要访问 array
的任何单个元素,您可以将其用作:
la $t3, array # put address of array into $t3
如果数组是字节数组,如:
array: .byte 'H','E','L','L','O'
访问第 ith 个元素:
lb $a0, i($t3) # this load the byte at address that is (i+$t3)
因为每个元素都是1个字节,所以要访问第i个字节,访问i
偏移到array
地址的地址。
您也可以通过以下方式访问它:
addi $t1,$t3,i
lb $a0,0($t1)
如果数组是单词数组,如:
array: .word 1,2,3,4,5,6,7,8,9
访问第 ith 个元素:
lw $a0, j($t3) #j=4*i, you will have to write j manually
因为每个元素都是 4 字节,要访问第 i 个 元素,您必须从 array
的起始地址移动 i*4
字节.
还有一些其他的访问方式:
li $t2, i # put the index in $t2
add $t2, $t2, $t2 # double the index
add $t2, $t2, $t2 # double the index again (now 4x)
add $t1, $t3, $t2 # get address of ith location
lw $a0, 0($t1)
示例 1:
.data
array: .byte 'H','E','L','L','O','_','W','O','R','L','D'
string: .asciiz "HELLO_WORLD"
size: .word 11
array1: .word 1,2,3,4,0,6,7,8,9
.text
.globl main
main:
li $v0, 11
la $a2,array
lb $a0,0($a2) #access 1st element of array or array[0]
syscall
lb $a0,1($a2) #access 2nd element of byte array or array[1]
syscall
lb $a0,2($a2) #access 3rd element of byte array or array[2]
syscall
lb $a0,10($a2) #access 11th element of byte array or array[10]
syscall
li $a0,10
syscall
syscall
li $v0,1
la $a3,array1
lw $a0,0($a3) #access 1st element of word array or array[0]
syscall
lw $a0,4($a3) #access 2nd element of word array or array[1]
syscall
lw $a0,8($a3) #access 3rd element of word array or array[2]
syscall
lw $a0,12($a3) #access 4th element of word array or array[3]
syscall
jr $ra
示例:
打印字节数组:
li $v0, 11
la $a2,array
lw $t0,size
loop1: #print array
lb $a0, 0($a2) #load byte at address stored in $a2
syscall
add $t0,$t0,-1
add $a2,$a2,1 #go to the next byte, since it is a byte array it will go to the address of next element
#to use it for printing word array instead of adding 1 add 4
bgtz $t0, loop1
我是 Mips assebly 的初学者,但根据我所学到的,我认为你可以这样做:
数组的每个元素都被分配了 4 个字节(它实际上可能更少,但没有其他元素将在这 4 个字节上存储任何内容,这些仅专用于一个元素)。
所以,在两个元素k,k+1的地址之间,有4bytes(always)的距离。
如上所述,如果你想到达 i-th 元素,你需要在第一个 (A[0]) 的地址中添加偏移距离,即 4*i.
除了 mul
指令之外,创建此偏移距离的一种方法是:
sll $t1, $t0, 2
这实际上意味着“将寄存器 $t0 中的值左移 2 位(用 0 填充其余部分)并将结果存储在寄存器 $t1 中。但是您可以很容易地注意到,如果您左移并填充零,对于每个班次,您实际上将当前值乘以 2(请注意,如果我们知道我们有足够的 space,我们会使用它以避免过度浮动)
因此,如果例如在 $t0 中,您在 $t1 中有 0001,您将获得 0100
所以基本上:你需要
sll $t1, $t0, 2 # [t1]=4i
lb $a0, t1($t0) # a0 = A[i]
*如果您是更有经验的 Mips 程序员,而我错了,请编辑我的 post 或评论以确保我们每个人都变得更好
我需要打印一个数组的单元格,我有一个包含单词 "HELLO_WORLD" 的数组,我设法自己打印一个索引,但我无法打印所有单元格一个,这是代码:
loop:
la $t0, hexdigits # address of the first element
lb $a0, 5($t0) # hexdigits[10] (which is 'A')
li $v0, 11 #system call service
syscall
addi $a0, $a0, 2
li $v0, 11 # I will assume syscall 11 is printchar (most simulators support it)
syscall # issue a system call
j end
是否可以使用指令 lb $a0, $s0($t0) 和一个我可以随时递增的寄存器?而不仅仅是一个数字?
这是我对您所追求的解决方案的最佳尝试。
.data
mystring: .asciiz "HELLO_WORLD" # zero-terminated string
.text
la $t0, mystring # Load the array
li $t1, 0 # Create the loop counter
li $v0, 11 # Syscall code for print character
loop:
add $t2, $t0, $t1 # Load the address for the element at the current index
lb $a0, 0($t2) # Load the value of the array at the current index into $a0
# (For printing)
beqz $a0, exit # If the value at the current index is null, you have
# reached the end of the string, so exit out
syscall # Print the character in $a0 (Syscall code in $v0: 11)
addi $t1, $t1, 1 # Increment the counter
j loop # Jump to the beginning of the loop
exit: # Should be reached once you have hit the end of the string
免责声明:我不懂 MIPS 汇编,我试着尽可能多地了解你的问题。我只能在不支持打印到屏幕(系统调用)的在线模拟器中测试这个程序。 不要只是盲目地粘贴此代码并回复“不,不起作用”。如果有任何问题,请尽量具体,我会尽力解决问题。
编者注:在修复 .asciiz
以确保有一个零终止符之后,即使在 .data 部分中其他非零数据紧随其后,对我来说看起来还不错。
v0=11
/ syscall
保留 $v0
不变,因此 li $v0, 11
可以被提升到循环之外。一些系统调用在 $v0
中放置了一个 return 值,但这个没有。 (MARS syscall docs)
我们可以直接递增 $t1
指针,而不是从 0 开始的计数器。
为了提高效率,我们可以“旋转”循环,使底部有一个 bnez $a0, loop
(不需要 j
),可能是通过剥离第一次迭代:加载并检查循环之前的一个字符,然后以打印为第一件事进入循环。然后递增、加载并检查下一个字符,然后跳出循环或跳到顶部打印它。
要访问 array
的任何单个元素,您可以将其用作:
la $t3, array # put address of array into $t3
如果数组是字节数组,如:
array: .byte 'H','E','L','L','O'
访问第 ith 个元素:
lb $a0, i($t3) # this load the byte at address that is (i+$t3)
因为每个元素都是1个字节,所以要访问第i个字节,访问i
偏移到array
地址的地址。
您也可以通过以下方式访问它:
addi $t1,$t3,i
lb $a0,0($t1)
如果数组是单词数组,如:
array: .word 1,2,3,4,5,6,7,8,9
访问第 ith 个元素:
lw $a0, j($t3) #j=4*i, you will have to write j manually
因为每个元素都是 4 字节,要访问第 i 个 元素,您必须从 array
的起始地址移动 i*4
字节.
还有一些其他的访问方式:
li $t2, i # put the index in $t2
add $t2, $t2, $t2 # double the index
add $t2, $t2, $t2 # double the index again (now 4x)
add $t1, $t3, $t2 # get address of ith location
lw $a0, 0($t1)
示例 1:
.data
array: .byte 'H','E','L','L','O','_','W','O','R','L','D'
string: .asciiz "HELLO_WORLD"
size: .word 11
array1: .word 1,2,3,4,0,6,7,8,9
.text
.globl main
main:
li $v0, 11
la $a2,array
lb $a0,0($a2) #access 1st element of array or array[0]
syscall
lb $a0,1($a2) #access 2nd element of byte array or array[1]
syscall
lb $a0,2($a2) #access 3rd element of byte array or array[2]
syscall
lb $a0,10($a2) #access 11th element of byte array or array[10]
syscall
li $a0,10
syscall
syscall
li $v0,1
la $a3,array1
lw $a0,0($a3) #access 1st element of word array or array[0]
syscall
lw $a0,4($a3) #access 2nd element of word array or array[1]
syscall
lw $a0,8($a3) #access 3rd element of word array or array[2]
syscall
lw $a0,12($a3) #access 4th element of word array or array[3]
syscall
jr $ra
示例: 打印字节数组:
li $v0, 11
la $a2,array
lw $t0,size
loop1: #print array
lb $a0, 0($a2) #load byte at address stored in $a2
syscall
add $t0,$t0,-1
add $a2,$a2,1 #go to the next byte, since it is a byte array it will go to the address of next element
#to use it for printing word array instead of adding 1 add 4
bgtz $t0, loop1
我是 Mips assebly 的初学者,但根据我所学到的,我认为你可以这样做:
数组的每个元素都被分配了 4 个字节(它实际上可能更少,但没有其他元素将在这 4 个字节上存储任何内容,这些仅专用于一个元素)。
所以,在两个元素k,k+1的地址之间,有4bytes(always)的距离。
如上所述,如果你想到达 i-th 元素,你需要在第一个 (A[0]) 的地址中添加偏移距离,即 4*i.
除了 mul
指令之外,创建此偏移距离的一种方法是:
sll $t1, $t0, 2
这实际上意味着“将寄存器 $t0 中的值左移 2 位(用 0 填充其余部分)并将结果存储在寄存器 $t1 中。但是您可以很容易地注意到,如果您左移并填充零,对于每个班次,您实际上将当前值乘以 2(请注意,如果我们知道我们有足够的 space,我们会使用它以避免过度浮动)
因此,如果例如在 $t0 中,您在 $t1 中有 0001,您将获得 0100 所以基本上:你需要
sll $t1, $t0, 2 # [t1]=4i
lb $a0, t1($t0) # a0 = A[i]
*如果您是更有经验的 Mips 程序员,而我错了,请编辑我的 post 或评论以确保我们每个人都变得更好