如何正确将MIPS汇编代码foo2转换为规范C代码?
MIPS汇编foo2转C代码的修正
原MIPS汇编代码
.global foo2 foo2: addi $t0,$zero,0 addi $t2,$zero,2 l1: slt $t6,$t0,$a1 beq $t6,$zero,e1 addi $t1,$zero,2 l2: slt $t6,$t1,$t2 beq $t6,$zero,e2 div $t2,$t1 mflo $t6 mul $t6,$t6,$t1 bne $t6,$t2,e3 addi $t1,$zero,2 addi $t2,$t2,1 j l2 e3: addi $t1,$t1,1 j l2 e2: sll $t6,$t0,2 add $t6,$t6,$a0 sw $t2,0($t6) addi $t0,$t0,1 addi $t2,$t2,1 j l1 e1: sll $t6,$t0,2 add $t6,$t6,$a0 addi $t0,$zero,0 sw $t0,0($t6) jr $ra
原C代码的逻辑偏差
原C代码用内层for循环时,会强制每次循环后自增j,这和汇编逻辑完全不符:
void foo2(int* lst, int n) { int i, j; int next = 2; for (i = 0; i < n; i++) { for (j = 2; j < next; j++) { if ((next / j) * j == next) { j = 2; next++; } } lst[i] = next; next++; } lst[i] = 0; }
汇编中bne $t6,$t2,e3的逻辑是:只有当(next/j)*j != next时,才会跳转到e3执行j自增;如果(next/j)*j == next,则重置j为2、next加1,且不执行j的自增,直接回到循环开头重新检查。
修正后的C代码
改用while循环精准匹配汇编的分支逻辑:
void foo2(int* lst, int n) { int i = 0; int next = 2; // 外层循环:生成n个质数存入数组 while (i < n) { int j = 2; // 内层循环:检查next是否为质数 while (j < next) { if ((next / j) * j == next) { // next能被j整除,不是质数,重置j并检查下一个数 j = 2; next++; } else { // 不能整除,继续检查下一个j j++; } } // 找到质数,存入数组 lst[i] = next; i++; next++; } // 数组末尾存入0 lst[i] = 0; }
逻辑对应说明
- 外层
while(i < n)对应汇编的l1循环,$t0对应变量i,$a1对应参数n - 内层
while(j < next)对应汇编的l2循环,$t1对应变量j,$t2对应变量next - 当
(next/j)*j == next时,对应汇编中bne不触发,执行重置j为2、next自增后跳回l2 - 当不相等时,跳转到
e3执行j自增后跳回l2 - 内层循环结束(j >= next)时,说明next是质数,存入数组后i和next自增,回到外层循环
- 外层循环结束后,给数组末尾赋值0,对应汇编的
e1部分
内容的提问来源于stack exchange,提问作者First_1st
相关产品推荐
相关产品推荐

