将 C for 循环的逻辑分解成我可以在 MIPS 中实现的东西? (计算数组中出现的次数)
Break down the logic for a C for-loop into something I can implement in MIPS? (count number occurrences in an array)
大家好,我正在将我的 C 代码转换为 MIPS,但问题是我无法为此做出正确的逻辑
for (int i=0;i<count;i++)
{
h[a[i]]++;
}
到目前为止我自己的逻辑是错误的
假设
a[]=$t1
b[]=$t2
li $s1,0
for:
bgt $s1,[size of array],end
lw $t3,($t1)
la $t1,4($t3)
lw $t4,($t2)
la $t2,4($t2)
sw $t3,0($t4)
add $s1,$s1,1
j for
我知道这是错误的..但在 MIPS 中它给我错误的地址错误和异常 7 和 4 错误
此外,如何将数组长度存入 MIPS 寄存器,例如 C 如何在不进行硬编码的情况下为您计算元素的数量?
int arr[]={1,3,5,7,9};
int n=sizeof(arr)/sizeof(arr[0]);
您需要了解递增的内容。获得这种理解的一种方法是分解:可以使用 Three-Address Code.
等方法分解表达式
那么建议分解一下:
h[a[i]]++;
如下:
int av = a[i];
h[av]++;
在这种方法中,我们将表达式的各种操作和元素分离到它们自己的代码行中,并使用引入的变量(也称为临时变量或 short-lived 变量)重新连接它们。
我们可以继续分解:
int av = a[i];
// decompose h[av]++;
int *hp = h + av;
*hp = *hp + 1;
但仍然:
int av = a[i];
int *hp = h + av;
// decompose *hp = *hp + 1;
int hv = *hp;
hv++;
*hp = hv;
这已经是分解得差不多了。希望您可以 (1) 将其转化为 MIPS 汇编 (2) 学习分解技术。
注意在C语言中,当一个数组,a
有int
个元素时,在a + i
和h + j
等表达式中有一个隐藏的乘法索引(i
和 j
)的 sizeof(int)
,即 4,称为加法之前发生的缩放 — 这种缩放在 C 中是自动的,必须在汇编中显式完成。
控制结构,即结构化语句也可以分解:
for (i = 0; i < count; i++) {
???
}
第一次分解:
i = 0;
while (i < count) {
???
i++;
}
进一步进入 if-goto-label 风格:
i = 0;
loop1:
if (i >= count) goto endLoop1;
???
i++;
goto loop1;
endLoop1:
注意循环退出条件是如何反转(否定)的——这是因为在 if-goto-label 中,我们写的是何时退出循环而不是像 C for/while 中那样何时继续循环,正好相反。
(情况并非总是如此:do-while 条件也说明何时继续循环,并且在汇编中,因为这是为下一次迭代放置向后分支的自然位置循环,do-while 和 if-goto-label 版本的条件测试将具有相同的条件意义——它们不是相反的——而 repeat-until in Pascal 使用相反的条件意义。)
另外 NB:<
的 inversion/negation/opposite 是 >=
。
分解是通过逻辑等价的变换来简化。只要我们保持逻辑等价,分解就会运行和原来一样。
大家好,我正在将我的 C 代码转换为 MIPS,但问题是我无法为此做出正确的逻辑
for (int i=0;i<count;i++)
{
h[a[i]]++;
}
到目前为止我自己的逻辑是错误的
假设
a[]=$t1
b[]=$t2
li $s1,0
for:
bgt $s1,[size of array],end
lw $t3,($t1)
la $t1,4($t3)
lw $t4,($t2)
la $t2,4($t2)
sw $t3,0($t4)
add $s1,$s1,1
j for
我知道这是错误的..但在 MIPS 中它给我错误的地址错误和异常 7 和 4 错误
此外,如何将数组长度存入 MIPS 寄存器,例如 C 如何在不进行硬编码的情况下为您计算元素的数量?
int arr[]={1,3,5,7,9};
int n=sizeof(arr)/sizeof(arr[0]);
您需要了解递增的内容。获得这种理解的一种方法是分解:可以使用 Three-Address Code.
等方法分解表达式那么建议分解一下:
h[a[i]]++;
如下:
int av = a[i];
h[av]++;
在这种方法中,我们将表达式的各种操作和元素分离到它们自己的代码行中,并使用引入的变量(也称为临时变量或 short-lived 变量)重新连接它们。
我们可以继续分解:
int av = a[i];
// decompose h[av]++;
int *hp = h + av;
*hp = *hp + 1;
但仍然:
int av = a[i];
int *hp = h + av;
// decompose *hp = *hp + 1;
int hv = *hp;
hv++;
*hp = hv;
这已经是分解得差不多了。希望您可以 (1) 将其转化为 MIPS 汇编 (2) 学习分解技术。
注意在C语言中,当一个数组,a
有int
个元素时,在a + i
和h + j
等表达式中有一个隐藏的乘法索引(i
和 j
)的 sizeof(int)
,即 4,称为加法之前发生的缩放 — 这种缩放在 C 中是自动的,必须在汇编中显式完成。
控制结构,即结构化语句也可以分解:
for (i = 0; i < count; i++) {
???
}
第一次分解:
i = 0;
while (i < count) {
???
i++;
}
进一步进入 if-goto-label 风格:
i = 0;
loop1:
if (i >= count) goto endLoop1;
???
i++;
goto loop1;
endLoop1:
注意循环退出条件是如何反转(否定)的——这是因为在 if-goto-label 中,我们写的是何时退出循环而不是像 C for/while 中那样何时继续循环,正好相反。
(情况并非总是如此:do-while 条件也说明何时继续循环,并且在汇编中,因为这是为下一次迭代放置向后分支的自然位置循环,do-while 和 if-goto-label 版本的条件测试将具有相同的条件意义——它们不是相反的——而 repeat-until in Pascal 使用相反的条件意义。)
另外 NB:<
的 inversion/negation/opposite 是 >=
。
分解是通过逻辑等价的变换来简化。只要我们保持逻辑等价,分解就会运行和原来一样。