在 MIPS 中实现一个在循环时交换的函数时是否需要 $s?
Is $s necessary when implementing a function that swaps while looping through a loop in MIPS?
void sort (int v[], int n)
{
int i, j;
for (i = 0; i<n; i+=1){
for(j=i-1; j>=0; && v[j]>v[j+1]; j-=1){
swap(v,j);
}
}
}
void swap(int v[], int k)
{
int temp;
temp = v[k+1];
v[k+1]= temp;
}
下面是swap函数的MIPS代码
swap : sll $t1, $a0, 2 // reg $t = k*4
add $t1, $a0, $t1 // reg $t1 = v+(k*4)
// reg $t1 has the address of v[k]
lw $t0, 0($t1) // reg $t0 (temp) =v[k]
lw $t2, 4($t1) // reg $t2 = v[k+1]
// refers to next element of v
sw $t2, 0($t1) // v[k] = reg $t2
sw $t0, 4($t1) // v[k+1] = reg $t0 (temp)
jr $ra // return to calling routine
我正在学习计算机体系结构。通过几个过程,我们了解到不应该改变的值使用堆栈指针存储或存储在$S
.
但是上面的代码中,sort函数的参数v[]
($a0
)和n
($a1
)存放在$s0
$s1
使用栈指针,在运行最内层循环之前,$s0
in $a0
,数据显示为将$s1的值赋值给$a1
.
但是上面的代码中,v[]
要在swap函数内部保持改变的状态,j
也要在循环的时候改变值,所以不需要保存并输入之前的值。
我的解释对吗?即在MIPS中实现上述代码时,使用栈指针不存储在$s
?
中是没有问题的
Is $s necessary when implementing a function that swaps while looping through a loop in MIPS?
$s
寄存器从来都不是必需的。必要的是 v
、n
、i
和 j
的变量值在对 swap
的函数调用后仍然存在。有两种方法可以使值在函数调用后存活下来,一种是使用(堆栈)内存,另一种是使用 $s
寄存器,因此,$s
寄存器根本不是必需的。 (两种形式都涉及栈内存(数量相同),但前者直接将栈内存用于变量值,后者将栈内存用于保存$s
寄存器的原始值) .
但是,$s
寄存器更适合具有多种用途的变量(通过运行时的指令执行动态测量,而不是代码清单中所见的静态测量),并且此类变量还必须在函数调用中存活下来。 (当然,数组不能存在于 $s
寄存器中,但对数组的引用(指针变量)可以。)
为什么这些变量必须在函数调用后继续存在?因为它们在调用之后都被消耗(使用,获取),尽管在函数调用之前已经定义(设置,目标)。无论函数调用是否发生,程序都期望变量的连续性。
让我们来看看高级语言和伪代码使用的逻辑变量与机器代码的物理存储之间的区别。
逻辑变量有名称、类型、scope/lifetime(它们来来去去,有些在程序执行期间经常出现,作为局部变量和参数)。有无数种可能——只要创建一个我们喜欢的新名称(也可以是未命名的,就像堆数据结构一样)。使用逻辑变量的程序期望连续性——一旦设置,变量将保留其值,直到被程序更改(然后保留该新值)。
机器的物理存储是永久的和全局的,只是位组。 CPU 寄存器始终存在,内存也是如此(让我们忽略虚拟化)。 CPU 看不到变量、它们的声明、它们的名称、它们的类型或它们的生命周期——CPU 看到物理存储。 (那么它是如何工作的?CPU 被告知,通过机器指令,如何与物理存储交互;它在每次运行机器代码指令时根据需要被告知。)
将高级语言程序翻译成机器代码的部分工作是管理程序逻辑变量到硬件物理存储的映射。由于物理存储有限制,机器代码程序必须在其中工作才能进行这些映射。
有时必须将逻辑变量重新定位到替代物理存储(例如,从 $a
寄存器到 $s
寄存器或堆栈内存)。通常需要机器代码指令(或序列)来进行此类重定位,此外,编译器或汇编程序员必须意识到从变量到存储的映射在同一程序的不同点可能不同。
(有时逻辑变量的值实际上位于多个物理存储位置,例如在操作内存中的全局变量时,副本被带入 CPU 寄存器以供使用。类似的是对于数组元素为真。)
void sort (int v[], int n)
{
int i, j;
for (i = 0; i<n; i+=1){
for(j=i-1; j>=0; && v[j]>v[j+1]; j-=1){
swap(v,j);
}
}
}
void swap(int v[], int k)
{
int temp;
temp = v[k+1];
v[k+1]= temp;
}
下面是swap函数的MIPS代码
swap : sll $t1, $a0, 2 // reg $t = k*4
add $t1, $a0, $t1 // reg $t1 = v+(k*4)
// reg $t1 has the address of v[k]
lw $t0, 0($t1) // reg $t0 (temp) =v[k]
lw $t2, 4($t1) // reg $t2 = v[k+1]
// refers to next element of v
sw $t2, 0($t1) // v[k] = reg $t2
sw $t0, 4($t1) // v[k+1] = reg $t0 (temp)
jr $ra // return to calling routine
我正在学习计算机体系结构。通过几个过程,我们了解到不应该改变的值使用堆栈指针存储或存储在$S
.
但是上面的代码中,sort函数的参数v[]
($a0
)和n
($a1
)存放在$s0
$s1
使用栈指针,在运行最内层循环之前,$s0
in $a0
,数据显示为将$s1的值赋值给$a1
.
但是上面的代码中,v[]
要在swap函数内部保持改变的状态,j
也要在循环的时候改变值,所以不需要保存并输入之前的值。
我的解释对吗?即在MIPS中实现上述代码时,使用栈指针不存储在$s
?
Is $s necessary when implementing a function that swaps while looping through a loop in MIPS?
$s
寄存器从来都不是必需的。必要的是 v
、n
、i
和 j
的变量值在对 swap
的函数调用后仍然存在。有两种方法可以使值在函数调用后存活下来,一种是使用(堆栈)内存,另一种是使用 $s
寄存器,因此,$s
寄存器根本不是必需的。 (两种形式都涉及栈内存(数量相同),但前者直接将栈内存用于变量值,后者将栈内存用于保存$s
寄存器的原始值) .
但是,$s
寄存器更适合具有多种用途的变量(通过运行时的指令执行动态测量,而不是代码清单中所见的静态测量),并且此类变量还必须在函数调用中存活下来。 (当然,数组不能存在于 $s
寄存器中,但对数组的引用(指针变量)可以。)
为什么这些变量必须在函数调用后继续存在?因为它们在调用之后都被消耗(使用,获取),尽管在函数调用之前已经定义(设置,目标)。无论函数调用是否发生,程序都期望变量的连续性。
让我们来看看高级语言和伪代码使用的逻辑变量与机器代码的物理存储之间的区别。
逻辑变量有名称、类型、scope/lifetime(它们来来去去,有些在程序执行期间经常出现,作为局部变量和参数)。有无数种可能——只要创建一个我们喜欢的新名称(也可以是未命名的,就像堆数据结构一样)。使用逻辑变量的程序期望连续性——一旦设置,变量将保留其值,直到被程序更改(然后保留该新值)。
机器的物理存储是永久的和全局的,只是位组。 CPU 寄存器始终存在,内存也是如此(让我们忽略虚拟化)。 CPU 看不到变量、它们的声明、它们的名称、它们的类型或它们的生命周期——CPU 看到物理存储。 (那么它是如何工作的?CPU 被告知,通过机器指令,如何与物理存储交互;它在每次运行机器代码指令时根据需要被告知。)
将高级语言程序翻译成机器代码的部分工作是管理程序逻辑变量到硬件物理存储的映射。由于物理存储有限制,机器代码程序必须在其中工作才能进行这些映射。
有时必须将逻辑变量重新定位到替代物理存储(例如,从 $a
寄存器到 $s
寄存器或堆栈内存)。通常需要机器代码指令(或序列)来进行此类重定位,此外,编译器或汇编程序员必须意识到从变量到存储的映射在同一程序的不同点可能不同。
(有时逻辑变量的值实际上位于多个物理存储位置,例如在操作内存中的全局变量时,副本被带入 CPU 寄存器以供使用。类似的是对于数组元素为真。)