使用MIPS完成汇编程序——选择排序实现

题目: 从键盘输入10个无符号字数并从大到小进行排序,排序结果在屏幕上显示出来。要求能输入数字 和输出数字 且由大到小来排列

1.代码以及伪代码:

首先写出对应c++代码然后把c++代码翻译成汇编语言

(1)c++代码

#include<iostream>
using namespace std;
//这里使用的是选择排序 
int main(){
    int a[10];
    int max, index;

    for (int i = 0; i < 10; i++) {
        cin >> a[i];        //输入10个数字
    }

    for(int i = 0; i < 9; i++) {

        max = a[i];     //初始化 max 和 index 
        index = i;

        for(int j = i + 1; j < 10; j++){
            if(max < a[j]) {
                max = a[j];    //如果a[j]大的话 max易主
                index = j;
            }    
        }
        a[index] = a[i];    //把扫完一遍后的最大值和a[i]交换,实现最大值被调到前面
        a[i] = max;
    }

    for(int i = 0; i < 10; i++) {
        cout << a[i] << " " << endl;  //输出
    }
} 

(2)翻译后的汇编语言以及注释

.text    # 代码段 声明
.globl main    # globl指明程序的入口地址main

#================================================================================

main:    # 程序入口地址
    la $a0,input_a_msg # 取字符串首地址
    li $v0,4    #4号功能调用,输出字符串
    syscall    #系统调用,输出字符串

    la $t6,arr     # $t6 是数组首地址  arr在数据段定义了 分配了10个空间
    move $t7,$zero   # $t7 是循环变量i 寄存器之间数据的直接交换  把t7变成0  相当于i = 0;
    addi $t8,$zero,10    # $t8 是数组长度 t8 = 10 + 0  所以t8 = 10;
    move $t9,$zero   # $t9 是循环变量j 把t9变成0  相当于j = 0;

#================================================================================
input:               # input代码块用于完成数组元素的输入

    li $v0,5  # 声明需要调用的操作代码为 5 (read_int) 并赋值给 $v0  这里相当于 cin >> a;
    syscall

    #==================================================
    # t0 = t7
    #t0 = t0*4
    # t1 = t6 + t0
    # 我们得到 t1 = t7 * 4 + t6  此时我们可以认为t1是数组将存元素的地址
    # t1 = v0 把刚输入的v0 放到数组中
    # SW  把一个字的数据从寄存器存储到存储器中 地址偏移量为0
    #==================================================

    move $t0,$t7     # 此处类似于C/C++中指针访问数组元素的方法
    mul $t0,$t0,4    # 数组元素所占字节数*循环变量+数组的起始地址=数组[循环变量]
    addu $t1,$t0,$t6 # '无符号数字相加
    sw $v0,0($t1)    # ''把$v0的数据存入到$t1中,地址偏移量为0

    addi $t7,$t7,1   # t7 = t7 +1 循环变量i自增
    blt $t7,$t8,input # 如果t7 小于数组长度(10)的话 也就是还没输入10个数字的话 就仍然进入input 直到输入10个数字后
    move $t7,$zero  # 完成输入后将循环变量置为0,可作为下一个循环的循环变量,以节省寄存器; $t7作为 i

#==============================================================
loop1:   #第一层循环 对每一个 a[i]
    # t9 = t7 + 1
    # t0 = t7 * 4
    # t1 = t0 + t6  由前面两个得到 t1 = 4 * t7 + t6  此时t1 是 数组元素首地址
    # 得到数组第0个元素 并且用t2 保存


    addu $t9,$t7,1   # 每次执行外层循环都将内层循环的循环变量置为i+1
    mul $t0,$t7,4    
    addu $t1,$t0,$t6  #获取a[i],作为max,即 t2 为max
    lw $t2,0($t1)  #偏移量,寻址 lw $t2, 0($t0) t0寄存器中的值作为地址, 把这个地址再加上偏移
                   #量0后 所起始的Word 复制到t2 中 这里t1已经是偏移后的下标了 对他偏移0 就是t1本身的值  
                   #这里我们把他赋值给max 实现代码中的刚进入循环就先把第一个当最大值
    move $t5,$t1  #把t5存t1 也就是下标i 进行初始化  这里会直接进入loop2里


#==============================================================
loop2:  #代表代码中的 if (max < a[j]){max = a[j]; index = j;}
    move $t0,$t9     
    mul $t0,$t0,4           
    addu $t4,$t0,$t6     # t4 = t9 * 4 + t6
    lw $t3,0($t4)        # 此时t3 就是 a[j]的值 t4为 j

    bge $t2,$t3,skip  # 如果max >= a[j],跳转到skip代码块 
    lw $t2,0($t4)    # 否则就执行下面这两句,赋值  把t2(max) 来保存 a[j]
    move $t5,$t4       #t5保存 j的值   t5就是index

#==============================================================  
#表示当 max >= a[j]时  跳过loop2 继续判断j的大小
skip:   
   addi $t9,$t9,1 # 内层循环变量j(t9)自增                      
   blt $t9,$t8,loop2  # 如果j < 10,则跳转到loop2 
   # 跳出第二层循环 
   lw $t4,0($t1) # 如果不满足,先进行赋值  t4 表示 a[i]
   sw $t4,0($t5)  # t4(a[i]) 存到 a[index]里
   sw $t2,0($t1) # a[i] 存到 max里 

   addi $t7,$t7,1 # 再将外层循环的循环变量自增
   addi $t4,$t7,1 #且判断是否还满足循环条件
   blt $t4,$t8,loop1 # 如果满足,则跳转到loop1

     # 如果不满足,则不跳转,继续执行下面的代码
output:
   la $a0,output_int_msg  #  打印字符串,提示用户即将输出程序
   li $v0,4
   syscall

   move $t7,$zero   # 将循环变量置为0,用于下一循环,节省寄存器

print:          # 实现打印数组元素
   move $t0,$t7
   mul $t0,$t0,4
   addu $t1,$t0,$t6
   lw $a0,0($t1)
   li $v0,1
   syscall

   la $a0,seperate  # 分隔数组元素
   li $v0,4
   syscall

   addi $t7,$t7,1
   blt $t7,$t8,print   # 如果满足循环条件,跳转到print继续执行循环


.data # 数据段声明
arr:.space 10 # 给arr分配10个空间
input_a_msg:.asciiz "Please input 10 abers and use 'Enter' to distinguish every aber\n"

output_int_msg:.asciiz "The result are as follows:\n"
seperate:.asciiz " "

2.汇编程序解释

首先 变量的初始化 对应5~6行
这里我需要 一个数组a 4个变量 i, j,max, index 这里虽然i和j是局部变量,但其实在汇编里面还是需要用一个寄存器来存储的
这里写图片描述
可以看到用 t6存首地址 t7存 i, t8存长度,t9存j max和index会在后面用到时分给某个寄存器的
其次是数组元素的的输入 对应8~10行
这里写图片描述
找到数组元素a[i] 是取出地址为 数组首地址 + i * 4
循环的话是用blt 来判断i是否小于10 如果仍小于10的话就回到input模块运行代码
所以循环就是用块 和 逻辑判断语句来实现

第一个循环 14~15行
这里写图片描述
代码很直白 addu 就是把j变成i+1并且进入下个循环 后面的就是做14~15行
的事情了。
第二循环 17`22行
这里写图片描述

如果满足max >= a[j]则跳过循环 即进入skip
这里写图片描述
skip是实现23~24以及外层循环的判断

输出函数 和输入一样 利用循环来实现打印功能

这里写图片描述

3.用PCSpim运行结果

这里写图片描述

posted @ 2018-04-13 11:12  qq874455953  阅读(774)  评论(0编辑  收藏  举报