美文网首页
MIPS模拟器MARS汇编入门

MIPS模拟器MARS汇编入门

作者: icfg66 | 来源:发表于2020-06-09 22:33 被阅读0次

    前言

    B站有个入门视频,文中的例子来自MIPS汇编语言小科普

    我会在代码中添加详细的注解,方便自己日后查看。这里使用的是MARS模拟器,很小巧方便。


    MARS模拟器

    三段小程序

    (1) Hello World!

    C语言的Hello World! 如何转变为汇编语言呢?

    #include<stdio.h>
    int main(){
        printf("Hello World!");
        return 0;
    }
    

    汇编语言实际上是对进行寄存器操作,需要向外输出,需要调用syscall指令,当v0(2号寄存器)的值为4时,输出a0(4号寄存器)保存地址处的"字符串"。字符串需要保存在.data字段,程序保存在.text字段,相当于main确定程序开始的地方。(#为注释)

     .data           #数据字段,保存要打印的字符串
      msg: .ascii "Hello World!\0"  #msg记录了数据的地址,.ascii告诉计算机编码类型
                                    #\0告诉计算机这里字符串结束
    .text          #代码字段,表示程序的入口,相当于main
      la $a0,msg   #$a0寄存器加载字段的地址,la表示load address加载地址指令
      li $v0,4     # $v0寄存器加载4,表示要显示字符串,li表示load immediate加载立即数指令
      syscall      # 调用字符串输出
    

    总体来看,汇编代码分成两段,数据段和代码段。printf输出函数需要连个寄存器v0, a0配合syscall指令完成。

    (2) IF-ELSE

    输入两个数,如果前者大,输出YES,反之NO。

    #include<stdio.h>
    int main(){
        int a,b;        
        scanf("%d",&a);
        scanf("%d",&b);
        if(a>b)
            printf("YES");
        else
            printf("NO");
      return 0;
    }
    

    这里同样要定义数据字段保存“YES”,“NO”,但多了一个终端输入部分,同样需要用syscall,但需要改变v0加载的值,变为5,输入的数据会保存在v0中。另外需要一个比较跳转语句bgt(greater 就跳)。最后需要一个程序结束命令,相当于return 0,同样调用syscall,但v0改为10。具体下

    .data              #数据段保存输出字符串,注意加\0
      msg_yes: .ascii "YES\0" 
      msg_no:  .ascii "NO\0"  
    
    
    .text               #程序段相当于main入口
      li $v0,5          #scanf("%d",&a);  t0保存a的值
      syscall 
      move $t0,$v0  
    
      li $v0,5          #scanf("%d",&b);  t1保存b的值
      syscall 
      move $t1,$v0 
    
      bgt $t0,$t1,s1    #a>b就跳转到标签s1,记录了地址
      la $a0,msg_no     #printf("NO");
      li $v0,4
      syscall 
    
      j stop            #直接跳转到结束语句stop
    
    s1:
      la $a0,msg_yes     #printf("YES");
      li $v0,4
      syscall 
    
      stop:             #结束程序语句,类似return 0;
      li $v0 10
      syscall 
    

    这里的j指令表示直接跳转,一般跟某个标签作为跳转地址,不会具体写内存地址。如果希望预留空间指定某个地址写程序,可以用.ktext 加地址。

    .ktext 0x0100  #stop标签的地址在内存0x100的位置上
     stop:   
      li $v0 10
      syscall 
    

    (3) WHILE

    计算1+2+...+100并输出

    #include<stdio.h>
    int main(){
        int i=1;
        int s=0;        
        while (i<=100){
            s=s+i;
            i=i+1;  
        }
        printf("%d",s);
      return 0;
    }
    

    我们需要两个寄存器保存i,s的值,while循环通过跳转指令,循环里面用加法指令,最后输出整型并返回,输出整型需要让v0=1,a0=s(和字符串不一样v0=4,a0是地址):

    .text           #main 入口
      li $t0,1      #t0表示i;t1表示s
      li $t1,0
    
    loop:
      add $t1,$t1,$t0  #s=s+i
      add $t0,$t0,1    #i=i+1
      ble $t0,100,loop #while(i<=100) .ble=branch if less or equal
    
      move $a0,$t0   #寄存器之间数据转移用move
      li $v0,1       #打印整数
      syscall        #printf("%d",s)
    
      li $v0, 10    #return 0;
      syscall     
    

    值得注意的是,这里没有数据段,不是必须的。

    总结

    • mips汇编代码一般分两端,数据段和代码段。其他段详情参见模拟器Help->MIPS->Directives
    • 输入输出返回等指令需要调用syscall,配合v0和a0,其他详情参加模拟器Help->MIPS->Syscalls
    功能 v0 a0
    输出整型 1 待输出整型
    输出字符串 4 待输出字符串地址
    输入整型 5
    返回 10
    • 用到的跳转指令:bgt(branch if greater than),j(jump),ble(branch if less or equal)
    • 用到的加载指令:move(寄存器间数据移动),li(加载立即数),la(加载地址)
    • 用到的运算指令:add

    更进一步的学习可以参看pdf:Introduction To MIPS Assembly Language Programming

    相关文章

      网友评论

          本文标题:MIPS模拟器MARS汇编入门

          本文链接:https://www.haomeiwen.com/subject/phtytktx.html