将这些C ++行转换为汇编/ mips时,我做错了什么?

时间:2016-09-26 22:13:50

标签: c++ assembly mips

for(int i = 0; i < 6; i++) {
   int temp = pos[i];
   x[temp] = data[i];
}

让我们说我已经用mips创建了数组,然后,

main:   la  $s1, x ## load address of x into $s1
la      $s2, pos  # load address of pos into $s2
la      $s3, data # load address of data into $s3 
li      $s6, 6 # for loop test. 
li  $s0, 0 # i variable

这就是我尝试将两行C ++翻译成mips的方法,

add     $t1, $s2, $s0 #  Get pos[i] and put in $t1;
sw      $t1, ($t3) # int temp = pos[i] 

add     $t2, $s3, $s0 # Get data[i] and put in #t2
add $t4, $s1, $t3  # Get x[temp] and store it in $t4
sw      $t2, ($t4)  #      x[temp] = data[i];   

addi    $s0, $s0, 1 #   i++ 
blt     $s0, $s6, for # (for i < 6)

但是当我在qtspim上运行它时(当与完整代码结合使用时)我得到的输出是

0 0 0 0 0 0 0 0 0 0

而不是

0 73 0 47 0 0 23 0 0 26

我应该得到的是什么......我做错了什么?谢谢。

1 个答案:

答案 0 :(得分:2)

你有一些基本结构正确并且有好的评论。

但是,有一些错误的单位化值,使用错误的寄存器而不实际从内存中取出。此外,索引值必须转换为字节偏移量。

我制作了两个版本的程序。带有bug注释的版本。并且,清理和工作版本。

这是带注释的版本[请原谅无偿的风格清理]:

 main:
    la      $s1,x                   # load address of x into $s1
    la      $s2,pos                 # load address of pos into $s2
    la      $s3,data                # load address of data into $s3
    li      $s6,6                   # for loop test.
    li      $s0,0                   # i variable

    # This is how I tried translating the two lines of C++ into mips,

for:
    # NOTE/BUG: for the index values, when adding them to the base address
    # of a given array, we need a _byte_ offset (i.e. the index multiplied by
    # 4)

    # NOTE/BUG: this does _not_ fetch pos[i] from memory -- it merely puts "i"
    # into the target
    add     $t1,$s2,$s0             #  Get pos[i] and put in $t1;

    # NOTE/BUG: $t3 is never initialized to anything
    sw      $t1,($t3)               # int temp = pos[i]

    # NOTE/BUG: this does _not_ fetch pos[i] from memory -- it merely puts "i"
    # into the target
    add     $t2,$s3,$s0             # Get data[i] and put in #t2

    # NOTE/BUG: $t3 should contain an _index_ value -- it would have to be
    # multiplied by 4 to create a _byte_ offset
    add     $t4,$s1,$t3             # Get x[temp] and store it in $t4
    sw      $t2,($t4)               #      x[temp] = data[i];

    addi    $s0,$s0,1               #   i++
    blt     $s0,$s6,for             # (for i < 6)

这是清理过的版本。我添加了缺少的代码,使其成为一个完整的可运行程序。我尽量保留原始代码,不幸的是,我不得不重构它:

    .text
    .globl  main
#
# for (int i = 0;  i < 6;  i++) {
#   int temp = pos[i];
#   x[temp] = data[i];
# }
main:
    la      $s1,x                   # load address of x into $s1
    la      $s2,pos                 # load address of pos into $s2
    la      $s3,data                # load address of data into $s3
    li      $s6,6                   # for loop test.
    li      $s0,0                   # i variable

    la      $a0,msg_pos
    move    $a1,$s2
    jal     print

    la      $a0,msg_data
    move    $a1,$s3
    jal     print

for:
    sll     $t0,$s0,2               # get byte offset for pos/data

    addu    $t1,$s2,$t0             # get address of pos[i]
    lw      $t1,0($t1)              # get value of pos[i] (i.e. temp)

    bltz    $t1,next                # skip negative indexes
    bge     $t1,6,next              # skip indexes that overflow

    sll     $t1,$t1,2               # convert temp to byte offset
    addu    $t1,$s1,$t1             # get address of x[temp]

    addu    $t2,$s3,$t0             # get address of data[i]
    lw      $t2,0($t2)              # get value of data[i]

    sw      $t2,0($t1)              # x[temp] = data[i]

next:
    addi    $s0,$s0,1               # i++
    blt     $s0,$s6,for             # (for i < 6)

    la      $a0,msg_x
    move    $a1,$s1
    jal     print

    li      $v0,10
    syscall

# print -- print array
#
# arguments:
#   a0 -- message pointer
#   a1 -- array pointer
print:
    li      $a2,6

    li      $v0,4
    syscall

print_loop:
    li      $v0,4
    la      $a0,msg_space
    syscall

    li      $v0,1
    lw      $a0,0($a1)
    syscall

    addiu   $a1,$a1,4
    addi    $a2,$a2,-1
    bgtz    $a2,print_loop

    li      $v0,4
    la      $a0,msg_nl
    syscall

    jr      $ra

    .data
pos:    .word   5, 0, 4, 1, 3, 2
data:   .word   1, 2, 3, 4, 5, 6
x:      .word   -1, -1, -1, -1, -1, -1

msg_pos:    .asciiz     "pos:"
msg_data:   .asciiz     "data:"
msg_x:      .asciiz     "x:"
msg_space:  .asciiz     " "
msg_nl:     .asciiz     "\n"

修改:虽然不是原始代码的一部分,但我在temp上添加了一个边界检查,因为它是问题类似问题的一部分,无论如何都很有道理。