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

What am I doing wrong when converting these lines of C++ into 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

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

您的一些基本结构是正确的,并且有 好评 条评论。

但是,在初始化值方面存在一些错误,使用了错误的寄存器并且实际上没有从内存中获取。此外,索引值必须转换为字节偏移量。

我已经为你的程序制作了两个版本。带有错误注释的版本。并且,一个清理和工作的版本。


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

 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 上添加了边界检查,因为它是所问的类似问题的一部分并且很有意义无论如何。