I've searched online and on this site and I can not find a good example of implementing a 2D Array in MIPS. I would 开发者_高级运维like to be able to see an example of how to go through the array in order to place data at a specific index and how to print the array out like shown below.
Such as a 5x5 array where $ would be the data in each index.
a b c d e
1 $ $ $ $ $
2 $ $ $ $ $
3 $ $ $ $ $
4 $ $ $ $ $
5 $ $ $ $ $
All you need to know about 2 Dimensional arrays:
- Allocate
- Implement nested loops
To allocate you you need to calculate ( #row X #column ) X #byte needed
regarding number of bytes you need 1 for char, 4 integer, 4 single precision float, 8 for double precision float. For example:
To dynamically allocate array of 150 double precision elements such that 15 rows and 10 column :
li $t1,15
li $t2,10
mul $a0, $t1, $t2
sll $a0, $a0, 3 # multiply number of elements by 2^3 = 8
# because each double precision floating point number takes 8 bytes
li $v0, 9
syscall
move $s0,$v0 # save array address in $s0
To get address of index (3,4) :
- Row major : 8 X (10 X 3 + 4) = 272 , then add it to the base address
- Column major : 8 X (15 X 4 + 3) = 504, then add it to the base address
Side note: I used shift left logical instead of multiply because shifting (sll
) in MIPS takes 1 clock cycle but mul
instruction takes 33 clock cycles. Thus, improving efficiency of the code.
Update / Edit (it has been over 3 years past since I wrote this answer, so I will improve my answer):
The pseudo-code to iterate through 2 dimensional matrix of integers (not doubles) in row-major format is the following:
for (int i = 0; i < array height; i++) {
for (int j = 0; j < array width; j++) {
prompt and read array value
row index = i
column index = j
memory[array base address + 4 * (array width * row index + column index)] = array value
}
}
However, pseudo-code to iterate through 2 dimensional matrix of integers (not doubles) in column-major format is the following:
for (int i = 0; i < array height; i++) {
for (int j = 0; j < array width; j++) {
prompt and read array value
row index = i
column index = j
memory[array base address + 4 * (array height * column index + row index)] = array value
}
}
Note: As we can see, the structure of the loop stays the same but the address calculation part has been slightly changed. Now implementing the above pseudo-codes are straightforward. We need 2 nested loops. Assuming:
$t0 <-- base address of array (or matrix or 2 dimensional array)
$t1 <-- height of matrix
$t2 <-- width of matrix
i <---- row index
j <---- column index
Implementation of reading values into row-major matrix:
.data
read_row_matrix_prompt_p: .asciiz "Enter an integer: "
###########################################################
.text
read_row_matrix:
li $t3, 0 # initialize outer-loop counter to 0
read_row_matrix_loop_outer:
bge $t3, $t1, read_row_matrix_loop_outer_end
li $t4, 0 # initialize inner-loop counter to 0
read_row_matrix_loop_inner:
bge $t4, $t2, read_row_matrix_loop_inner_end
mul $t5, $t3, $t2 # $t5 <-- width * i
add $t5, $t5, $t4 # $t5 <-- width * i + j
sll $t5, $t5, 2 # $t5 <-- 2^2 * (width * i + j)
add $t5, $t0, $t5 # $t5 <-- base address + (2^2 * (width * i + j))
li $v0, 4 # prompt for number
la $a0, read_row_matrix_prompt_p
syscall
li $v0, 5 # read a integer number
syscall
sw $v0, 0($t5) # store input number into array
addiu $t4, $t4, 1 # increment inner-loop counter
b read_row_matrix_loop_inner # branch unconditionally back to beginning of the inner loop
read_row_matrix_loop_inner_end:
addiu $t3, $t3, 1 # increment outer-loop counter
b read_row_matrix_loop_outer # branch unconditionally back to beginning of the outer loop
read_row_matrix_loop_outer_end:
Implementation of reading values into column-major matrix:
.data
read_col_matrix_prompt_p: .asciiz "Enter an integer: "
###########################################################
.text
read_col_matrix:
li $t3, 0 # initialize outer-loop counter to 0
read_col_matrix_loop_outer:
bge $t3, $t1, read_col_matrix_loop_outer_end
li $t4, 0 # initialize inner-loop counter to 0
read_col_matrix_loop_inner:
bge $t4, $t2, read_col_matrix_loop_inner_end
mul $t5, $t4, $t1 # $t5 <-- height * j
add $t5, $t5, $t3 # $t5 <-- height * j + i
sll $t5, $t5, 2 # $t5 <-- 2^2 * (height * j + i)
add $t5, $t0, $t5 # $t5 <-- base address + (2^2 * (height * j + i))
li $v0, 4 # prompt for number
la $a0, read_col_matrix_prompt_p
syscall
li $v0, 5 # read a integer number
syscall
sw $v0, 0($t5) # store input number into array
addiu $t4, $t4, 1 # increment inner-loop counter
b read_col_matrix_loop_inner # branch unconditionally back to beginning of the inner loop
read_col_matrix_loop_inner_end:
addiu $t3, $t3, 1 # increment outer-loop counter
b read_col_matrix_loop_outer # branch unconditionally back to beginning of the outer loop
read_col_matrix_loop_outer_end:
You can set up a 2D array in terms of a 1D array. You just need to correctly map elements from the 1D array to the 2D array. This site has pictures:
http://www.plantation-productions.com/Webster/www.artofasm.com/Windows/HTML/Arraysa2.html#1010609
You can use a standard format for addressing each cell. For example:
a b c d e
1 0 1 2 3 4
2 5 6 7 8 9
3 10 11 12 13 14
4 15 16 17 18 19
5 20 21 22 23 24
You should be able to see the pattern :) In general, if there are M columns and N rows, the cell at row i, column j (zero-indexed) can be accessed at point i * M + j - 1
精彩评论