在将数组的地址传递给 MIP 中的函数后,我是否应该将数组的值保存到堆栈中?
After passing the address of an array into a function in MIPs, am I supposed to save the values of the array into a stack?
我必须将这个 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)
For updatePoint, should I be storing the values of arg[0] - arg[2] onto the stack?
不,arg
是一个 数组 。它由 reference 传递(即 arg
的 pointer/address 在 $a0
中)。根据 return,arg
中的值 预计 将被 updatePoint
修改。它 将 修改 arg[0]
和 arg[1]
(即见 updatePoint
的最后两行),并且有条件地, 可能 一路修改arg[2]
和arg[3]
在updatePoint
中的每一步,它必须使用arg
中的更新值,并且, return,updatePoint
的 caller 必须接收回 arg
和 modified 值。
updatePoint
中的任何内容都不允许 findDistance
修改 arg
,因为 findDistance
的所有参数都由 value[=96= 传递].
因此,您需要保留 [指针值] $a0
以防止 updatePoint
将此 指针 值丢失到 arg
当调用 findDistance
时。
您 可以 将它保存在 updatePoint
的堆栈帧中,但您必须在每次调用 findDistance
后重新加载它。最好将其保存在 callee 保留的寄存器中(例如 $s0
),这样 findDistance
就不会打扰它。
这是第一次调用 findDistance
的示例。填写其他内容以及最后两行 C++ 行对您来说应该很容易。请注意 nothing else 需要保留在 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
至 return.
对于 $ra
,该函数可以将其保存在(例如)$t3
中,然后再保存 jr $t3
。调用者不关心$ra
是否被保留(即用你想要的任何reg做jr
,惯用的是$ra
) .只需确保函数 returns 到正确的位置。
在上面的代码中,请注意在调用 findDistance
之后,测试 return 值 [in $v0
]。之后,不需要 return 值,代码使用 $v0
作为临时值(对比(例如)$t0
))。
同样,被调用的函数可以使用参数寄存器 $a0-$a3
为所欲为(即 它们 可以在计算期间用作临时寄存器)
这是你的 c++ 函数,我称之为 "simple C"。它更像是对 asm:
的直接翻译
void
updatePoint(int *arg)
{
int distance;
distance = findDistance(arg[0], arg[1], 0, -1);
if (distance >= 1)
goto noset1;
if (arg[2] >= 0)
goto noset1;
arg[2] = -arg[2];
noset1:
distance = findDistance(arg[0], arg[1], 10, -1);
if (distance >= 1)
goto noset2;
if (arg[2] <= 0)
goto noset2;
arg[2] = -arg[2];
noset2:
distance = findDistance(arg[0], arg[1], -1, 0);
if (distance >= 1)
goto noset3;
if (arg[3] >= 0)
goto noset3;
arg[3] = -arg[3];
noset3:
distance = findDistance(arg[0], arg[1], -1, 10);
if (distance >= 1)
goto noset4;
if (arg[3] <= 0)
goto noset4;
arg[3] = -arg[3];
noset4:
arg[0] = arg[0] + arg[2];
arg[1] = arg[1] + arg[3];
}
我必须将这个 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)
For updatePoint, should I be storing the values of arg[0] - arg[2] onto the stack?
不,arg
是一个 数组 。它由 reference 传递(即 arg
的 pointer/address 在 $a0
中)。根据 return,arg
中的值 预计 将被 updatePoint
修改。它 将 修改 arg[0]
和 arg[1]
(即见 updatePoint
的最后两行),并且有条件地, 可能 一路修改arg[2]
和arg[3]
在updatePoint
中的每一步,它必须使用arg
中的更新值,并且, return,updatePoint
的 caller 必须接收回 arg
和 modified 值。
updatePoint
中的任何内容都不允许 findDistance
修改 arg
,因为 findDistance
的所有参数都由 value[=96= 传递].
因此,您需要保留 [指针值] $a0
以防止 updatePoint
将此 指针 值丢失到 arg
当调用 findDistance
时。
您 可以 将它保存在 updatePoint
的堆栈帧中,但您必须在每次调用 findDistance
后重新加载它。最好将其保存在 callee 保留的寄存器中(例如 $s0
),这样 findDistance
就不会打扰它。
这是第一次调用 findDistance
的示例。填写其他内容以及最后两行 C++ 行对您来说应该很容易。请注意 nothing else 需要保留在 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
至 return.
对于 $ra
,该函数可以将其保存在(例如)$t3
中,然后再保存 jr $t3
。调用者不关心$ra
是否被保留(即用你想要的任何reg做jr
,惯用的是$ra
) .只需确保函数 returns 到正确的位置。
在上面的代码中,请注意在调用 findDistance
之后,测试 return 值 [in $v0
]。之后,不需要 return 值,代码使用 $v0
作为临时值(对比(例如)$t0
))。
同样,被调用的函数可以使用参数寄存器 $a0-$a3
为所欲为(即 它们 可以在计算期间用作临时寄存器)
这是你的 c++ 函数,我称之为 "simple C"。它更像是对 asm:
的直接翻译void
updatePoint(int *arg)
{
int distance;
distance = findDistance(arg[0], arg[1], 0, -1);
if (distance >= 1)
goto noset1;
if (arg[2] >= 0)
goto noset1;
arg[2] = -arg[2];
noset1:
distance = findDistance(arg[0], arg[1], 10, -1);
if (distance >= 1)
goto noset2;
if (arg[2] <= 0)
goto noset2;
arg[2] = -arg[2];
noset2:
distance = findDistance(arg[0], arg[1], -1, 0);
if (distance >= 1)
goto noset3;
if (arg[3] >= 0)
goto noset3;
arg[3] = -arg[3];
noset3:
distance = findDistance(arg[0], arg[1], -1, 10);
if (distance >= 1)
goto noset4;
if (arg[3] <= 0)
goto noset4;
arg[3] = -arg[3];
noset4:
arg[0] = arg[0] + arg[2];
arg[1] = arg[1] + arg[3];
}