在将数组的地址传递给MIP中的函数之后,我是否应该将数组的值保存到堆栈中?

时间:2016-10-17 03:36:17

标签: mips

我必须将这个C ++函数翻译成MIPS。

void updatePoint(int *arg)
    {
      int distance;

      distance = findDistance(arg[0],arg[1],0,-1);
      if ((distance < 1) && (arg[2] < 0))
        arg[2] = - arg[2];
      distance = findDistance(arg[0],arg[1],10,-1);
      if ((distance < 1) && (arg[2] > 0))
        arg[2] = - arg[2];
      distance = findDistance(arg[0],arg[1],-1,0);
      if ((distance < 1) && (arg[3] < 0))
        arg[3] = - arg[3];
      distance = findDistance(arg[0],arg[1],-1,10);
      if ((distance < 1) && (arg[3] > 0))
        arg[3] = - arg[3];
       arg[0] = arg[0] + arg[2];
      arg[1] = arg[1] + arg[3];
      return;
}

这是导致函数调用的MIPS代码。

        .data
redData:    .word   0:4
greenData:      .word   0:4
prmpt1:  .asciiz "Enter x-coordinate for red particle (0 to 10):"
prmpt2:  .asciiz "Enter y-coordinate for red particle (0 to 10):"
prmpt3:  .asciiz "Enter x-coordinate for green particle (0 to 10):"
prmpt4:  .asciiz "Enter y-coordinate for green particle (0 to 10):"
prmpt5:  .asciiz "cycle "
prmpt6:  .asciiz "red particle (x,y,xVel,yVel): "
prmpt7:  .asciiz "green particle (x,y,xVel,yVel): "
prmpt8:  .asciiz "Collison: oops, end of simulation!\n"
space:   .asciiz " "
endl:    .asciiz "\n"

# i     $s0
# cycle $s1 = 0
# dist  $s2

.text

main:   li      $s1,0

la      $s3,redData     #  redData[2] = 1 ;
li      $s4,1
sw      $s4,8($s3)
sw      $s4,12($s3)     #  redData[3] = 1 ;
la      $s3,greenData   #  greenData[2] = -1 ;
li      $s4,-1
sw      $s4,8($s3)
sw      $s4,12($s3)     #  greenData[3] = -1 ;

la      $a0,prmpt1      #  cout << prmpt1 ;
li      $v0,4
syscall
la      $s3,redData
li      $v0,5           #  cin >> redData[0] ;
syscall
sw      $v0,($s3)
la      $a0,prmpt2      #  cout << prmpt2 ;
li      $v0,4
syscall
li      $v0,5           #  cin >> redData[1] ;
syscall
sw      $v0,4($s3)
la      $a0,prmpt3      #  cout << prmpt3 ;
li      $v0,4
syscall
la      $s3,greenData   #  cin >> greenData[0] ;
li      $v0,5
syscall
sw      $v0,($s3)
la      $a0,prmpt4      #  cout << prmpt4 ;
li      $v0,4
syscall
li      $v0,5           #  cin >> greenData[1] ;
syscall
sw      $v0,4($s3)

loop:                           #  do {
la      $a0,prmpt5      #    cout << "cycle " << cycle << endl ;
li      $v0,4
syscall
move    $a0,$s1
li      $v0,1
syscall
la      $a0,endl
li      $v0,4
syscall
la      $a0,prmpt6      #    cout << "red particle (x,y,xVel,yVel): "
li      $v0,4
syscall
la      $s3, redData
lw      $a0,($s3)       #       << redData[0]
li      $v0,1
syscall
la      $a0,space       #       << " "
li      $v0,4
syscall
lw      $a0,4($s3)      #       << redData[1]
li      $v0,1
syscall
la      $a0,space       #       << " "
li      $v0,4
syscall
lw      $a0,8($s3)      #       << redData[2]
li      $v0,1
syscall
la      $a0,space       #       << " "
li      $v0,4
syscall
lw      $a0,12($s3)     #       << redData[3]
li      $v0,1
syscall
la      $a0,endl        #       << endl ;
li      $v0,4
syscall
la      $a0,prmpt7      #    cout << "green particle (x,y,xVel,yVel): "
li      $v0,4
syscall
la      $s3, greenData
lw      $a0,($s3)       #       << greenData[0]
li      $v0,1
syscall
la      $a0,space       #       << " "
li      $v0,4
syscall
lw      $a0,4($s3)      #       << greenData[1]
li      $v0,1
syscall
la      $a0,space       #       << " "
li      $v0,4
syscall
lw      $a0,8($s3)      #       << greenData[2]
li      $v0,1
syscall
la      $a0,space       #       << " "
li      $v0,4
syscall
lw      $a0,12($s3)     #       << greenData[3]
li      $v0,1
syscall
la      $a0,endl        #       << endl ;
li      $v0,4
syscall
la      $a0,endl        #       << endl ;
li      $v0,4
syscall

la      $a0,redData     #    updatePoint(redData) ;
jal     updatePoint

对于updatePoint,我应该将arg [0] - arg [2]的值存储到堆栈中吗?为此,我应该

lw      $s0, 0($a0) 
lw      $s1, 4($a0)
lw      $s2, 8($a0)
lw      $s3, 12($a0)
addi    $sp, $sp, -20
lw      $s0, 0($sp) 
lw      $s1, 4($sp)
lw      $s2, 8($sp)
lw      $s3, 12($sp)
lw      $ra, 16($sp)

1 个答案:

答案 0 :(得分:2)

  

对于updatePoint,我应该将arg [0] - arg [2]的值存储到堆栈中吗?

不,arg数组。它由引用传递(即arg的指针/地址在$a0)。返回后,arg中的值预期将被updatePoint修改。它修改arg[0]arg[1](即查看updatePoint的最后两行),并且有条件地,可以修改{{一路上有1}}和arg[2]

arg[3]的每一步,必须使用updatePoint中的更新的值,并在返回时来电< arg的/ em>必须使用已修改的值接收updatePoint

arg中的任何内容都不允许updatePoint修改arg,因为findDistance的所有参数都是通过传递的。

因此,您需要保留[{1}}中的[指针值],以防止findDistance在调用{{$a0时将此指针值丢失为updatePoint 1}}制作。

可以将其保存在arg的堆栈框架中,但是您必须在每次调用findDistance后重新加载它。最好将其保存在被调用者保留的寄存器中(例如updatePoint),以便findDistance不会打扰它。

这是第一次调用$s0的示例。你应该很容易填写其他的以及最后两个C ++行。请注意, nothing 其他需要保存在findDistance中[这是一个强烈的提示]。您可以根据需要使用尽可能多的其他临时注册表。

findDistance

请注意,被调用的函数只需保留updatePoint,必须保留# void # updatePoint(int *arg) # { # int distance; # # distance = findDistance(arg[0], arg[1], 0, -1); # if ((distance < 1) && (arg[2] < 0)) # arg[2] = -arg[2]; # # distance = findDistance(arg[0], arg[1], 10, -1); # if ((distance < 1) && (arg[2] > 0)) # arg[2] = -arg[2]; # # distance = findDistance(arg[0], arg[1], -1, 0); # if ((distance < 1) && (arg[3] < 0)) # arg[3] = -arg[3]; # # distance = findDistance(arg[0], arg[1], -1, 10); # if ((distance < 1) && (arg[3] > 0)) # arg[3] = -arg[3]; # # arg[0] = arg[0] + arg[2]; # arg[1] = arg[1] + arg[3]; # } updatePoint: subu $sp,$sp,8 sw $ra,4($sp) sw $s0,0($sp) # NOTE: now that we've preserved $s0 of our caller, we are free to use it # for whatever we want -- we use it to preserve the address of 'arg' move $s0,$a0 # preserve address of 'arg' # distance = findDistance(arg[0], arg[1], 0, -1); lw $a0,0($s0) # get arg[0] lw $a1,4($s0) # get arg[1] li $a2,0 # set 0 li $a3,-1 # set -1 jal findDistance # if ((distance < 1) && (arg[2] < 0)) bge $v0,1,noset1 # distance < 1? if no, fly lw $v0,8($s0) # get arg[2] bgez $v0,noset1 # is arg[2] < 0? if no, fly # arg[2] = -arg[2]; neg $v0,$v0 # get -arg[2] sw $v0,8($s0) # set arg[2] = -arg[2] noset1: # with adjusted parameters repeat the above for all three remaining calls # perform last two lines of function ... lw $ra,4($sp) lw $s0,0($sp) addu $sp,$sp,8 jr $ra findDistance: ,并且必须保留$s0-$s7以便它可以$sp返回

对于$ra,该函数可以将其保存在(例如)jr $ra中,然后再保存$ra。如果保留$t3或不保留jr $t3,则来电者关心(即$ra使用您希望的任何注册表,其中惯用的是jr)。只需确保函数返回到正确的位置。

在上面的代码中,请注意在调用$ra后,会测试返回值[in findDistance]。之后,不需要返回值,代码使用$v0作为临时值(相对于(例如)$v0))。

同样,被调用的函数可以使用参数寄存器$t0来满足它的意愿(即它们可以在计算期间用作临时寄存器)

这里的c ++函数被重新编码为我所称的&#34;简单的C&#34;。它更像是对asm的直接翻译:

$a0-$a3