We're given the following code in C and asked to translate it into MIPS. We don't need to handle lo and hi; they're stored for us in $a0 and $a1:
void decode_request(unsigned long int request, int* array) {
// lo and hi are already stored for us in $a0 and $a1
unsigned lo = (unsigned)((request << 32) >> 32);
unsigned hi = (unsigned)(request >> 32);
for (int i = 0; i < 6; ++i) {
array[i] = lo & 0x0000001f;
lo = lo >> 5;
}
unsigned upper_three_bits = (hi << 2) & 0x0000001f;
array[6] = upper_three_bits | lo;
hi = hi >> 3;
for (int i = 7; i < 11; ++i) {
array[i] = hi & 0x0000001f;
hi = hi >> 5;
}
This is my attempt of it:
.globl decode_request
decode_request:
li $t0, 0 # int i = 0;
first_loop:
bge $t0, 6, after_first_loop # branch if greater than or equal to 6
mul $t0, $t0, 4 # account for ints; storage size = word
and $t1, $a0, 0x0000001f # lo & 0x0000001f;
sw $t1, 4($t1) # array[i] = lo & 0x0000001f;
srl $t2, $a0, 5 # lo >> 5;
sw $t2, 0($t2) # lo = lo >> 5;
add $t0, $t0, 1 # ++i
j first_loop # jump back to top of loop
after_first_loop:
sll $t3, $a1, 2 # (hi << 2)
and $t3, $t3, 0x0000001f # & 0x0000001f
mul $t3, $t3, 4 # account for ints; storage size = word
sw $t3, 0($t3) # store back into memory
or $t4, $t3, $a0 # array[6] = upper_three_bits | lo;
sw $t4, 24($t4) # store back into memory; use 24 since int = 4 bytes and we have offset of 6
srl $a1, $a1, 3 # hi >> 3;
sw $a1, 0($a1) # hi = hi >> 3;
second_loop:
li $t5, 7 # int i = 7;
bge $t0, 11, end # branch if greater than or equal to 11
mul $t5, $t5, 4 # account for ints; storage size = word
and $t6, $a1, 0x0000001f # hi & 0x0000001f
sw $t6, 4($t6) # array[i] = hi & 0x0000001f;
srl $t7, $a0, 5 # hi >> 5;
sw $t7, 0($t7) # lo = lo >> 5;
add $t5, $t5, 1 # ++i
j second_loop # jump back to top of second_loop
end:
jr $ra
Any ideas as to where I could be going wrong, or possibly other approaches?
Thank you!
I have corrected the first part of your code. And 80% of instructions where incorrect syntactically. This is something that the asm should have told you. And many, many logical errors. One of the main is that you need to manage addresses of the array elements.
decode_request:
li $t0, 0 # int i = 0;
### we assume $t4=@array and $t5=array[i]
add $t5, $t4, zero ## t5=&array[0]
first_loop:
### bge is bge reg1, reg2, offset. Cant use an immediate
### slti does a compare and then a branch is possible
sltiu $t1, $t0, 6 # i<6 ?
beq $t0, zero, after_first_loop # false ? goto end first loop
### i=i*4??? what is it supposed to do?
####mul $t0, $t0, 4 # account for ints; storage size = word
### and $t1, $a0, 0x0000001f ... should be andi
andi $t1, $a0, 0x0000001f # lo & 0x0000001f;
### not sw $t1, 4($t1) which does not make sense
### array[i] is $t5 and data to store is $t1
sw $t1, 0($t5) # array[i] = lo & 0x0000001f;
srl $t2, $a0, 5 # lo >> 5;
### why do you want to store lo? Just keep it is register $t2.
### And your store is anyway incorrect. Should be sw $t2,0($t6)
#### where $t6 is the address of lo
## sw $t2, 0($t2) # lo = lo >> 5;
### add add $t0 ... should be addi
addi $t0, $t0, 1 # ++i
#### and you must increment array address
addi $t5, $t5, 4 # $t5++ -> $t5==array[i+1]
j first_loop # jump back to top of loop
Now try to correct the rest of your program. Errors in the asm should be explicit.
I've used Alain's corrections to try and do the second loop
loop_two:
# these loops go from 0-5 and then from 7-10
# since t5 has been incremented each time, $t5 = array[5]
# have to add 8 to get $t5 = array[7]
# do this in between_loops
slti $t7, $t6, 11 # i < 11 ?
beq $t6, zero, end # if false, done with loop, go to end
# loop body goes here
andi $t6, $a1, 0x0000001f # hi & 0x0000001f
# array[i] is $t5 and data to store is $t6
sw $t6, 0($t5) # array[i] = hi & 0x0000001f;
srl $t7, $a0, 5 # hi >> 5;
add $t6, $t6, 1 # ++i
addi $t5, $t5, 4 # increment array address, $t5++ -> $t5==array[i+1]
j loop_two
This assumes that the code below was declared in decode_request
li $t6, 7 # t3 is our second counter (int i = 7)
User contributions licensed under CC BY-SA 3.0