C到MIPS - 指令引用未定义QTSpim

时间:2017-03-13 00:59:03

标签: c assembly mips

我正在尝试从C转换为MIPS,但是我在jal main中得到了一个指令引用错误。以下是我要翻译的内容:

void swap (int a, int b)
{
   int temp=a;
   a=b;
   b=temp;
}


int distance (int a, int b)
{
   if (b > a) 
      swap (a,b);   

  return (a-b)
}

这就是我写的:

.data       #declare the variables
    var1:   .word 4, 7, 12, 5
    var2:   .word 15, 3, 6, 14
    result: .space 4

.text
main:
    la $t0, var1    #load address 'var1' into $t0
    la $t1, var2    #load address 'var2' into $t1
    la $t2, result  #load address 'result' into $t2

    li $t3, 0       # load imm (i=0)

for_loop:
    bgt $t3, 4, for_done        #when i>4 do not meet condition, exit
    lw $t4, 0($t4)      #result[i] = tmp 
    jal distance
    addi $t3, $t3, 1        #i++
    j for_loop

for_done:
    la $t2, distance
    ori $v0, $0, 4
    syscall


distance:
    blt $t0, $t1, exit
    jal swap
    sub $t5, $t0, $t1
    jr $t5

swap:
    lw $t6, 0($t0)
    lw $t7, 0($t1)

    sw $t6, 0($t1)
    sw $t7, 0($t0)

exit:

我其实不知道我在做什么,只是大会的基础知识。我希望你们中的一些人可以帮助我。 :)

1 个答案:

答案 0 :(得分:1)

对不起,但你的asm代码至少有15个错误。

我创建了两个版本:一个带有注释的bug,另一个带有修复的bug和一个工作程序

请注意,由于C代码含糊不清,我不得不猜测该程序的真实意图并获得[相当多]诗意许可。

这里是带有注释错误的未更改版本[请原谅无偿的样式清理]:

    .data                           # declare the variables
var1:       .word       4, 7, 12, 5
var2:       .word       15, 3, 6, 14

# NOTE/BUG: this only reserves 4 bytes instead of the 16 we need to hold all
# four values
result:     .space      4

    .text

main:
    la      $t0,var1                # load address 'var1' into $t0
    la      $t1,var2                # load address 'var2' into $t1
    la      $t2,result              # load address 'result' into $t2

    li      $t3,0                   # load imm (i=0)

for_loop:
# NOTE/BUG: this goes one too far (i.e. we want i>=4)
    bgt     $t3,4,for_done          # when i>4 do not meet condition, exit

# NOTE/BUG: $t4 is never intialized to anything, so this instruction will fault
# (e.g. equivalent to dererencing a null pointer in C)
    lw      $t4,0($t4)              # result[i] = tmp

    jal     distance

# NOTE/BUG: the index variable 'i' is incremented, but distance does _not_ use
# (i.e.) distance will always use var1[0] and var2[0] on each iteration
    addi    $t3,$t3,1               # i++
    j       for_loop

# NOTE/BUG: what do we want to do here? -- print the result vector presumably
# NOTE/BUG: syscall 4 is to print a string -- it would require setting up $a0
# and _not_ $t2 but, even then, using 'distance' is wrong as distance is the
# function name and _not_ a string so we'd get garbage
# NOTE/BUG: we probably wouldn't even get that far because QtSpim would
# probably fault because distance is in the .text segment and not the .data
# segment
for_done:
    la      $t2,distance
    ori     $v0,$0,4
    syscall

distance:
# NOTE/BUG: this is comparing _addresses_ instead of _values_ (i.e.) this
# compares (&var1[i] > &var2[i]) instead of var1[i] > var2[i])
# NOTE/BUG: this test is _reversed_, because this guarantees negative numbers
    blt     $t0,$t1,exit

# NOTE/BUG: jal is calling swap as a function, but swap is merely a label here
    jal     swap

# NOTE/BUG: based on the mips ABI, return values go into $v0
    sub     $t5,$t0,$t1

# NOTE/BUG: when 'jal distance' is called, the return address goes into $ra
# and to return to the place in main that called us, we want to do 'jr $ra'
# NOTE/BUG: this 'jr' should be at exit:
    jr      $t5

# NOTE/BUG: this actually swaps var1[i] and var2[i] -- would this be correct to
# modify the original arrays???
swap:
    lw      $t6,0($t0)
    lw      $t7,0($t1)

    sw      $t6,0($t1)
    sw      $t7,0($t0)

# NOTE/BUG: this is where the 'jr' should go
exit:

这是清理后的工作版本。我决定它应该在结果向量中存储距离,然后显示所有三个向量:

    .data
# NOTE: lw/sw must be four byte aligned so keep these first
var1:       .word       4, 7, 12, 5
var2:       .word       15, 3, 6, 14
result:     .space      16

msg_var1:   .asciiz     "var1:"
msg_var2:   .asciiz     "var2:"
msg_result: .asciiz     "dist:"
msg_space:  .asciiz     " "
msg_nl:     .asciiz     "\n"

    .text

main:
    la      $s0,var1                # load address of 'var1'
    la      $s1,var2                # load address of 'var2'
    la      $s2,result              # load address of 'result'
    li      $s3,4                   # number of elements in a given vector

    li      $s4,0                   # load imm (i=0)

for_loop:
    bge     $s4,$s3,for_done        # i <= count? if no, fly
    jal     distance
    addi    $s4,$s4,1               # i++
    j       for_loop

for_done:
    la      $a0,msg_var1
    la      $a1,var1
    jal     show

    la      $a0,msg_var2
    la      $a1,var2
    jal     show

    la      $a0,msg_result
    la      $a1,result
    jal     show

    # exit program
    li      $v0,10
    syscall

# distance -- calculate distance between two numbers in two vectors
#
# RETURNS:
#   stores into 'result' vector
#
# global registers:
#   s0 -- pointer to var1
#   s1 -- pointer to var2
#   s2 -- pointer to result
#   s4 -- array index
#
# registers:
#   t0 -- address and value of var1[i]
#   t1 -- address and value of var2[i]
#   t2 -- temp value
#   t7 -- byte offset corresponding to index 'i'
distance:
    sll     $t7,$s4,2               # convert index to byte offset

    addu    $t0,$s0,$t7             # get &var1[i]
    lw      $t0,0($t0)              # fetch var1[i]

    addu    $t1,$s1,$t7             # get &var2[i]
    lw      $t1,0($t1)              # fetch var2[i]

    bge     $t0,$t1,distance_done   # swap a/b to get abs val? if no, fly

    # swap a/b
    move    $t2,$t0                 # temp = a
    move    $t0,$t1                 # a = b
    move    $t1,$t2                 # b = temp

distance_done:
    sub     $v0,$t0,$t1             # get distance (i.e.) abs(a-b)

    addu    $t2,$s2,$t7             # get &result[i]
    sw      $v0,0($t2)              # result[i] = distance

    jr      $ra                     # return

# show -- show vector
#
# arguments:
#   a0 -- vector name
#   a1 -- pointer to vector
#
# registers:
#   t3 -- array remaining count
#
# clobbers:
#   v0
show:
    li      $v0,4                   # syscall to print string
    syscall

    move    $t3,$s3                 # get number of elements in vector

show_loop:
    blez    $t3,show_done           # more to do? if no, fly

    li      $v0,4
    la      $a0,msg_space           # output a space
    syscall

    # output vector[i]
    li      $v0,1                   # syscall to output value
    lw      $a0,0($a1)              # get vector value
    syscall

    addiu   $a1,$a1,4               # advance pointer to next array element
    addi    $t3,$t3,-1              # bump down count
    j       show_loop

show_done:
    # output newline
    la      $v0,4
    la      $a0,msg_nl
    syscall

    jr      $ra                     # return