汇编语言实现的快速排序(MIPS)

本文仅讨论如何用汇编语言实现一个简单的快速排序算法,不探讨快速排序算法的原理;若读者对于快速排序算法还不熟悉,请自行阅读其它文章。

一、相关软件

MARS(MIPS Assembler and Runtime Simulator),下载连接:

计算机组成原理全套实验软件(包含电路仿真器)网盘下载icon-default.png?t=N6B9https://pan.baidu.com/s/1YfnpPLGUR7H8OmYJloujjQ
提取码: mips 

安装注意:MIPS为JAVA可执行文件(Executable Jar File),需要先安装JAVA环境(包含在其中)

二、根据C语言编写汇编代码

本部分主要通过对应的C语言代码来编写对应的MIPS汇编语言代码,适用于汇编语言的初学者,对于熟练者可以直接编写。

完整代码在第三部分

快速排序算法的C语言代码如下:

#include <stdio.h>

void quick_sort(int *arr, int start, int end);

int main() {
    int arr[] = {9, 8, 7, 6, 4, 5, 3, 2};
    int len = sizeof(arr) / sizeof(arr[0]);

    quick_sort(arr, 0, len - 1);

    printf("The Result is:\n");
    for (int i = 0; i < len; i++) {
        printf("%d", arr[i]);
        printf(" ");
    }

    return 0;
}

void quick_sort(int *arr, int start, int end) {
    if (end <= start) return;
    //取第一个元素为支点
    int pivot = arr[start];
    int left = start + 1;
    int right = end;

    while (left <= right) {
        if (arr[left] <= pivot) {
            left++;
        } else if (arr[right] >= pivot) {
            right--;
        } else {
            int tmp = arr[left];
            arr[left] = arr[right];
            arr[right] = tmp;
            left++;
            right--;
        }
    }

    int tmp = arr[right];
    arr[right] = arr[start];
    arr[start] = tmp;

    quick_sort(arr, start, right - 1);
    quick_sort(arr, right + 1, end);
}

(1)数据声明

.data
Array:
	.align 2
	.word 9,8,7,6,4,5,3,2
Space:
	.asciiz " "
Str:
	.align 0
	.ascii "The Result is:\n"

Array数组保存要排序的数组和排序之后的数组,以字(32比特)对齐,因此在之后的读写该数组时,需要将字地址乘以4得到字节地址的偏移量!!!

(2)编写主函数

.globl  main
main:
	li $a0,0
	li $a1,28
	jal quick_sort
	li $t0,0
	li $t1,32
	la $a0,Str
	jal print_str
	L:
		lw $a0,Array($t0)
		addi $t0,$t0,4
		jal print_int
		la $a0,Space
		jal print_str
		bne $t0,$t1,L
	li $v0,17
	li $a0,0
	syscall

主函数主要的功能为调用快速排序函数和输出运行结果,数组一共有8个字,因此其字节地址的偏移范围为0-28,放在参数寄存器$a0和$a1里面,对应C语言中的start和end

(3)快速排序函数(递归)

quick_sort:
	slt $t3,$a1,$a0
	bne $t3,$zero,Exit
	
	addi $sp,$sp,-16
	sw $a0,-12($sp)
	sw $a1,-8($sp)
	sw $ra,-4($sp)
	
	addi $t0,$a0,0
	addi $t1,$a1,0
	
	lw $t2,Array($t0) 	#支点
	li $s2,-1
	sw $s2,Array($t0)
	
	Loop:
		slt $t3,$t0,$t1
		beq $t3,$zero,End
		lw $s0,Array($t0)
		lw $s1,Array($t1)
		
		bne $s0,$s2,Else
		slt $t3,$s1,$t2
		beq $t3,$zero,E1
		sw $s0,Array($t1)
		sw $s1,Array($t0)
		j Loop
		E1:
			addi $t1,$t1,-4
			j Loop
		Else:
			slt $t3,$t2,$s0
			beq $t3,$zero,E2
			sw $s0,Array($t1)
			sw $s1,Array($t0)
			j Loop
		E2:
			addi $t0,$t0,4
			j Loop
	End:
	sw $t2,Array($t0)
	sw $t0,0($sp)
	
	lw $a0,-12($sp)
	lw $a1,-8($sp)
	addi $a1,$t0,-4
	jal quick_sort
	
	lw $a0,-12($sp)
	lw $a1,-8($sp)
	lw $t0,0($sp)
	addi $a0,$t0,4
	jal quick_sort
		
	lw $a0,-12($sp)
	lw $a1,-8($sp)
	lw $ra,-4($sp)
	addi $sp,$sp,16
	Exit:
	jr $ra

下面详解该函数的基本过程:
1.首先判断 $a1 (end)是否小于 $a0(end),如果是,该过程为叶过程,直接返回;否则为非叶过程,为函数开辟栈空间,保存两个参数寄存器的内容和$ra中的返回地址;

2.将 $t0 和 $t1 分别赋值为 $a0 和 $a1,并将数组中的第一个元素作为支点存放在 $t2 中,原数组的位置置为-1

3.进入循环,首先判断当前数组下标是否已经超过结束位置,如果是退出循环,直接跳转到 End 标签;否则取出当前下标对应的数组元素放入 $s0(称为当前位置元素) 和结束位置对应的数组元素放入 $s1(称为结束位置元素)

4.判断当前元素($s0)是否等于支点元素($t2):

如果是,则比较结束位置元素和支点元素的大小,如果结束位置元素小于支点元素,则将结束位置元素存放在当前位置,将当前元素存放在结束位置,然后跳转到循环开始处;如果结束位置元素大于或等于支点元素,则将结束位置下标减 4(数组下标向前移动一位),继续循环

反之,则比较当前元素和支点元素的大小。如果当前元素大于或等于支点元素,则比较结束位置元素和支点元素的大小,如果结束位置元素小于支点元素,则将结束位置元素存放在当前位置,将当前元素存放在结束位置,然后跳转到循环开始处。如果结束位置元素大于或等于支点元素,则将当前下标加 4(数组下标向后移动一位),继续循环

5.最后$t0的数值即为支点的位置,将这个值保存入栈,递归调用快速排序函数对支点元素左边的子数组和右边的子数组进行排序

6.销毁栈帧,退出函数

三、完整的汇编代码

.data
Array:
	.align 2
	.word 9,8,7,6,4,5,3,2
Space:
	.asciiz " "
Str:
	.align 0
	.ascii "The Result is:\n"

.text
.globl  main
main:
	li $a0,0
	li $a1,28
	jal quick_sort
	li $t0,0
	li $t1,32
	la $a0,Str
	jal print_str
	L:
		lw $a0,Array($t0)
		addi $t0,$t0,4
		jal print_int
		la $a0,Space
		jal print_str
		bne $t0,$t1,L
	li $v0,17
	li $a0,0
	syscall
quick_sort:
	slt $t3,$a1,$a0
	bne $t3,$zero,Exit
	
	addi $sp,$sp,-16
	sw $a0,-12($sp)
	sw $a1,-8($sp)
	sw $ra,-4($sp)
	
	addi $t0,$a0,0
	addi $t1,$a1,0
	
	lw $t2,Array($t0) 	#支点
	li $s2,-1
	sw $s2,Array($t0)
	
	Loop:
		slt $t3,$t0,$t1
		beq $t3,$zero,End
		lw $s0,Array($t0)
		lw $s1,Array($t1)
		
		bne $s0,$s2,Else
		slt $t3,$s1,$t2
		beq $t3,$zero,E1
		sw $s0,Array($t1)
		sw $s1,Array($t0)
		j Loop
		E1:
			addi $t1,$t1,-4
			j Loop
		Else:
			slt $t3,$t2,$s0
			beq $t3,$zero,E2
			sw $s0,Array($t1)
			sw $s1,Array($t0)
			j Loop
		E2:
			addi $t0,$t0,4
			j Loop
	End:
	sw $t2,Array($t0)
	sw $t0,0($sp)
	
	lw $a0,-12($sp)
	lw $a1,-8($sp)
	addi $a1,$t0,-4
	jal quick_sort
	
	lw $a0,-12($sp)
	lw $a1,-8($sp)
	lw $t0,0($sp)
	addi $a0,$t0,4
	jal quick_sort
		
	lw $a0,-12($sp)
	lw $a1,-8($sp)
	lw $ra,-4($sp)
	addi $sp,$sp,16
	Exit:
	jr $ra

print_int:
	addi $v0,$zero,1
	syscall 
	jr $ra
	
print_str:
	addi $v0,$zero,4
	syscall
	jr $ra

四、运行结果

 

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
冒泡排序是一种简单的排序算法,可以用MIPS汇编语言实现。下面是一个基于MIPS汇编语言的冒泡排序示例: ``` # $a0 - 存放数组的起始地址 # $a1 - 数组长度 .data array: .word 5, 2, 3, 8, 6 # 初始化一个数组 newline: .asciiz "\n" .text .globl main main: la $a0, array # 将数组地址存储在$a0中 lw $a1, array+4 # 将数组长度存储在$a1中 addi $a1, $a1, -1 # 数组长度-1 outerloop: li $t0, 1 # 将标志位$t0设置为1 li $t1, 0 # 将$i的初值设置为0 innerloop: add $t2, $a0, $t1 # 计算第$i个元素的地址 lw $t3, ($t2) # 将第$i个元素存储在$t3中 addi $t4, $t1, 4 # 计算下一个元素的地址 add $t5, $a0, $t4 # 计算下一个元素的地址 lw $t6, ($t5) # 将下一个元素存储在$t6中 ble $t3, $t6, skipswap # 如果$t3 <= $t6,则跳过交换 sw $t3, ($t5) # 否则,交换$t3和$t6 sw $t6, ($t2) li $t0, 0 # 设置标志位$t0为0,表示进行了交换 skipswap: addi $t1, $t1, 4 # 增加$i的值 blt $t1, $a1, innerloop # 如果$i < n - 1,则继续循环 beqz $t0, outerloop # 如果标志位$t0为0,则继续外部循环 # 打印排序后的数组 li $v0, 4 la $a0, newline syscall la $a0, array printloop: lw $a1, ($a0) li $v0, 1 syscall la $a0, newline li $v0, 4 syscall addi $a0, $a0, 4 blt $a0, array+20, printloop li $v0, 10 # 退出程序 syscall ``` 在上面的示例代码中,我们首先定义了一个包含一些随机数字的数组。然后,我们使用`lw`指令将数组的起始地址存储在寄存器`$a0`中,将数组长度存储在寄存器`$a1`中。接下来,我们使用两个循环来实现冒泡排序。外部循环用于控制每一轮比较和交换,内部循环用于比较和交换相邻的元素。最后,我们使用`syscall`指令将排序后的数组打印出来。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值