我必须将这个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)
答案 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