MIPS下的冒泡排序

来源:互联网 发布:php 二级分类 编辑:程序博客网 时间:2024/05/22 06:06

MIPS汇编语言的特点在于整齐划一。
本文主要实现冒泡排序算法。话不多说,先给出其中两个函数的c语言代码

void swap(int v[],int k){    int temp;    temp=v[k];    v[k]=v[k+1];    v[k+1]=temp;}void sort(int v[],int n){    int i,j;    for(i=0;i<n;i++)        for(j=i-1;j>=0 && v[j] > v[j+1] ; j-=1)        {            swap(v,j);        }}

下面给出MIPS代码:
(备注:程序是基于WINMIPS64模拟器下运行)

;;实现冒泡排序;.data ;数据区    before: .asciiz "Before sort the array is:\n"    after:  .asciiz "After sort the array is:\n"     array: .word 5,2,4,8,0,1,3,9,7,6  ;初始的矩阵    CONTROL: .word32 0x10000    DATA:    .word32 0x10008.text ;代码区    main:         lwu  $t8,DATA($zero) ;将CONTROL和DATA地址读取到寄存器        lwu  $t9,CONTROL($zero)        ;输出提示信息,提示下面输出内容为排序前的数组        daddi $t6,$zero,4      ;4表示输出类型为ascii的字符串        daddi $t7,$zero,before ;把字符串的首地址加载到t7        sd $t7,0($t8)          ;把字符串的地址写到数据字的映射内存中        sd $t6,0($t9)          ;把类型4写入到控制字的映射内存中        jal output             ;输出排序前的数组        daddi $a0,$zero,array  ;准备参数1,数组的首地址        daddi $a1,$zero,10     ;准备参数2,数组的大小        jal bubblesort             ;调用排序函数        ;输出提示信息,提示下面输出内容为排序后的数组        daddi $t6,$zero,4      ;4表示输出类型为ascii的字符串        daddi $t7,$zero,after ;把字符串的首地址加载到t7        sd $t7,0($t8)          ;把字符串的地址写到数据字的映射内存中        sd $t6,0($t9)          ;把类型4写入到控制字的映射内存中        jal output             ;输出排序后的数组        j final    ;用于输出数组的内容      output:         daddi $t0,$zero,10  ;$t0=len=10        daddi $t1,$zero,0   ;$t1=i=0        daddi $t6,$zero,1   ; 1表示输出类型为整形数        for:            slt  $t2,$t1,$t0 ;判断i<len,若小于len则t2的值变成0            beqz $t2,out     ;判断t2的值是否为0,若为0则跳转到out            dsll  $t3,$t1,3  ;t3=i*8 左移3位相当于乘上8,得到第i个数字的偏移地址            ld $t7,array($t3);计算出第i个数字的实际地址            sd $t7,0($t8)    ;把第i个数字的地址写入到数据字的映射内存中            sd $t6,0($t9)    ;把类型1写入到控制字的映射内存中            daddi $t1,$t1,1  ;i=i+1             j for           out: jr $ra;排序函数   bubblesort:        dadd $s7,$zero,$ra ;保存返回地址,因为嵌套调用swap会改变ra的值        dadd $s2,$zero,$a0 ;保存传进来的第一个参数,第一个参数为数组的首地址        dadd $s3,$zero,$a1 ;保存传进来的第二个参数,第二个参数为数组的大小        daddi $s0,$zero,0 ;外层循环,i初始化为0,i=0forout: slt   $t0,$s0,$s3 ;若i不满足小于数组长度n,则跳出循环        beqz  $t0,exitout        daddi $s1,$s0,-1  ;内层循环j=i-1forin:  slti  $t0,$s1,0   ;如果j小于0,则退出循环        bne   $t0,$zero,exitin        dsll   $t1,$s1,3   ;t1=j*8 ,计算出第j个数字的偏移地址        dadd  $t2,$t1,$s2 ; 计算第j个数字的实际地址        lw    $t3,0($t2)  ;取出第j个数字的值        lw    $t4,8($t2)  ;取出第j+1个数字的值        slt   $t0,$t4,$t3 ;如果第j+1个数大于第j个数,则跳出内部循环        beqz  $t0,exitin          dadd  $a0,$zero,$s2  ;准备第一个参数,也就是数组的首地址        dadd  $a1,$zero,$s1  ;准备第二个参数,也就是j的值,之后调用的sawp函数将交换第j和j+1个数        jal   swap     ;跳转到子程序        daddi $s1,$s1,-1 ;j=j-1        j     forin        exitin:            daddi $s0,$s0,1            j     forout        exitout:            dadd $ra,$zero,$s7 ;把之前保存的返回主程序的地址返回ra            jr $ra;交换函数swap:           dsll   $t1,$a1,3 ;$a1中存放着j值,现在计算实际偏移量        dadd  $t1,$a0,$t1 ;获取第j个值的实际地址,$a0中存放着数组的首地址        lw    $t0,0($t1)  ;获得第j个数的值        lw    $t2,8($t1)  ;获得第j+1个数的值        sw    $t2,0($t1)   ;交换两个数        sw    $t0,8($t1)        jr    $rafinal: halt

部分知识点总结:
$a0~$a3 寄存器用于传递参数
• j imm 跳转到一个地址
jr reg 跳转到寄存器中的地址
jal imm 跳转到一个子程序
• 单层调用可以不用保存$ra寄存器中的返回地址,但如果被调用程序使用到了调用程序中使用的保存寄存器$s0~$s7,则也需要在堆栈中保存相应的寄存器的值。注意:堆栈使用前必须先初始化栈指针的值。
• 嵌套调用的过程中,例如程序中的main调用了bubbleSort,而bubbleSort调用了swap,这样就属于嵌套调用,所以必须保存bubbleSort返回main函数的地址。而调用swap的过程称为叶过程,因此可以不用保存返回地址。另外,必要时,其他保存寄存器中的值也需要保存。
• 可通过add $ t0, $zero,$t1 实行将 $t1中的值copy到$t0寄存器中
• 双字类型的,一般在前面加d。例如双字的加为dadd,而单字的加为add 。

原创粉丝点击