C到MIPS的转换:解码器

时间:2019-02-27 23:26:58

标签: c mips code-translation

我们在C语言中获得了以下代码,并要求将其转换为MIPS。我们不需要处理lo和hi;它们为我们存储在$ a0和$ 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;
  }

这是我的尝试:

.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

关于我可能会出错的地方或其他方法的任何想法吗?

谢谢!

2 个答案:

答案 0 :(得分:1)

我已更正了您代码的第一部分。并且80%的指令在语法上不正确。这是汇编应该告诉您的。还有很多很多逻辑错误。 主要之一是您需要管理数组元素的地址。

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

现在尝试更正程序的其余部分。 asm中的错误应该是明确的。

答案 1 :(得分:0)

我已经使用Alain的更正来尝试进行第二次循环

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

这假定下面的代码在decode_request中声明了

li $t6, 7   # t3 is our second counter (int i = 7)