【问题标题】:Converting C to MIPS assembly将 C 转换为 MIPS 程序集
【发布时间】:2014-01-24 09:30:59
【问题描述】:

我有这段用 C 语言编写的代码,我想将其转换为 MIPS 程序集,我尝试使用提供 .s 文件的编译器,但这对我来说似乎是胡言乱语。有人可以提供一些帮助,因为我对 MIPS 组装一无所知。

我的代码是 Collat​​z 猜想。我的 C 编程不是很好,因为到目前为止我只学过 Java。提前致谢

#include<stdio.h>

int main()
{
    int n;

    printf("Enter an integer\n");
    scanf("%d", &n);


    while (n != 1)
    {
        if(n == 1)
        {   
            printf("N == 1");
        }
        else if((n%2)==0)
        {
            printf("Integer is even : %d\n", n);
            n = n/2;
        }
        else
        {
            n = 3*n + 1;
            printf("Integer has been multipled by 3 and added by 1 : %d\n", n);
        }
   }
}

【问题讨论】:

  • 快速评论 - if(n == 1) {printf("N == 1"); } 永远无法执行,因为您的 while 条件会阻止它。
  • 哦,是的,谢谢!完全错过了!
  • 请考虑此代码在翻译为asm 时将包含对 C 标准库的引用。尝试以更简单的形式重写它作为开始。您还使用了哪些命令行选项?
  • 不要使用制表符,因为它会破坏缩进,在这里和其他地方。
  • 要获得更干净的 ASM:制定一个从 main() 调用的例程,并忽略 printf() 的。然后显示这个例程的 ASM,不会太多。考虑到this,解释起来并不难。

标签: c assembly mips


【解决方案1】:

这是对代码的重新排列,将输入和输出置于算法例程 collatz() 之外。

#include <stdio.h>

int steps;

void print(int n)
{
    printf("%d ", n);
    steps++;
}

void collatz(int n)
{
    print(n);
    while (n != 1)
    {
        if ((n % 2) == 0)
        {
            n = n / 2;
            print(n);
        }
        else
        {
            n = 3 * n + 1;
            print(n);
        }
    }
}

int main()
{
    int n;

    printf("Enter an integer\n");
    scanf("%d", &n);

    steps = 0;
    collatz(n);
    printf("in %d steps.\n", steps);
}

对于 n = 6,这将被打印出来:

6 3 10 5 16 8 4 2 1 in 9 steps.

很酷的算法,谢谢介绍!

【讨论】:

    【解决方案2】:

    当人们使用编译器编译 C 代码时,他们必须记住这是供机器使用的代码,因此通常不是人类认为可读性好的代码的好例子。

    也就是说,这是我对您在 MIPS 汇编中的源代码的解释。这是为与 SPIM 模拟器一起使用而编写的,并使用其对 I/O 的系统调用,如文档 here 所述。

    .data  
    
    prompt:        .asciiz "Enter an integer\n"
    neq1Message:   .asciiz "N == 1"
    nevenMessage:  .asciiz "Integer is even : "
    noddMessage:   .asciiz "Integer has been multiplied by 3 and added by 1 : "
    
    .text  
    main:
    
        #print prompt
        la $a0 prompt
        addi $v0 $zero 4
        syscall
    
        #read integer into $t0
        addi $v0 $zero 5
        syscall
        move $t0 $v0 
    
        loop:
    
            # quit loop if n == 1
            addi $t1 $zero 1
            beq  $t0 $t1 loopEnd
    
            #skip to even if n != 1
            addi $t1 $zero 1
            bne  $t0 $t1 neven
    
            neq1:
    
                # print n is 1
                la $a0 neq1Message
                addi $v0 $zero 4
                syscall
    
                j loop
    
            neven:
    
                # skip to odd if n not even
                andi $t1 $t0 1
                bne  $t1 $zero nodd
    
                # print n is even
                la $a0 nevenMessage
                addi $v0 $zero 4
                syscall
    
                # print n
                move $a0 $t0
                addi $v0 $zero 1
                syscall
    
                # print newline
                addi $a0 $zero 10
                addi $v0 $zero 11
                syscall
    
                # n = n / 2
                srl $t0 $t0 1
    
                j loop
    
            nodd:
    
                # n = 3 * n + 1
                addi $t1 $zero 3
                mul  $t0 $t0 $t1
                addi $t0 $t0 1
    
                # print n is odd
                la $a0 noddMessage
                addi $v0 $zero 4
                syscall
    
                # print n
                move $a0 $t0
                addi $v0 $zero 1
                syscall
    
                # print newline
                addi $a0 $zero 10
                addi $v0 $zero 11
                syscall
    
                j loop
    
        loopEnd:
    
    jr $ra
    

    【讨论】:

    • 感谢您的代码,虽然它的数学运算错误,但它可以工作,例如,当我输入 6 时,它不会将其除以 2,出于某种原因将其更改为 10
    • @user3166873 实际上,这里的代码与上面的 C 执行相同的数学运算——我得到两个版本的相同输出。回想一下,首先将 6 减半为 3,然后乘以 3,再加上 1 得到 10。请注意第二,在您的 C 代码中,数字在显示后除以 2。
    猜你喜欢
    • 2021-09-13
    • 1970-01-01
    • 1970-01-01
    • 2015-08-13
    • 2023-03-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多