/* 简单说明:这是计算机组成与设计实验课的第一次实验,与理论课上学的MIPS语法比较对口,算是一次实战。写在这里是为了记录、备份以及巩固。以下内容有部分是参考自其他网站。*/
一.实验目的
1.认识和掌握MIPS汇编语言程序设计的基本方法。
2 熟悉PCSpim模拟器的使用。
二.实验内容
从键盘输入10个无符号字数并从大到小进行排序,排序结果在屏幕上显示出来。
三.实验器材
电脑一台、PCSpim模拟器软件一套。
四.实验过程
1)设计流程图:
2)代码实现:
#C++代码
###################################################################
# // 从键盘输入10个无符号字数并从大到小进行排序,排序结果在屏幕上显示出来
# #include <iostream>
# using namespace std;
# int main() {
# int array[10];
# for (int i = 0; i < 10; i++)
# cin >> array[i];
# for (int i = 0; i < 9; i++) {
# for (int j = 0; j < 9-i; j++) {
# if (array[j] < array[j+1]) {
# int temp = array[j];
# array[j] = array[j+1];
# array[j+1] = temp;
# }
# }
# }
# for (int i = 0; i < num; i++)
# cout << array[i] << ' ';
# return 0;
# }
###################################################################
# MIPS汇编语言代码
.text # 代码段以 .text 为开始标志,即各项指令操作
.globl main # 定义 main 为外部程序可以访问的标签
main: # 程序入口
li $v0, 4 # 操作码$v0 = 4, 将要打印的字符串赋给 $a0
la $a0, input_msg; # la(load address), 打印字符串,提示用户输入排序数组长度
syscall # 调用操作系统完成打印(输出)
la $t6, array # $t6 为数组首地址
move $t7, $zero # $t7 为循环变量i, i = 0
move $t8, $zero # $t8 为数组长度
addi $t8, $t8, 10 # $t8 = 10
move $t9, $zero # $t9 是循环变量j, j = 0
input: # input代码块用于完成数组元素的读入
li $v0, 5 # 操作码$v0 = 5, 将读取的整型赋值给$v0, cin >> $t0
syscall
# array[i] = $t0
move $t0, $t7 # 此处类似C/C++中指针访问数组元素的方法
mul $t0, $t0, 4 # 此处第二个$t0表示的应该是下标
addu $t1, $t0, $t6 # $t1为需要访问的元素的地址
sw $v0, 0($t1) # 将下标对应的值存到$v0
addi $t7, $t7, 1 # i++
blt $t7, $t8, input # if i < 10, jump to input
move $t7, $zero # 输入结束,将循环变量$t7置为0,节省寄存器
loop1: # 此为外层循环,将内层循环的变量置为0,
move $t9, $zero # j = 0
loop2:
# 获取 array[j]
move $t0, $t9 # $t0 = $t9 = j
mul $t0, $t0, 4 # $t0 = array[j]与array[0]的地址差
addu $t1, $t0, $t6 # $t1 = array[j]
lw $t2, 0($t1) # 将 arrat[j] 放入寄存器$t2中
# 获取 array[j+1]
addi $t0, $t9, 1 # j++
mul $t0, $t0, 4 # $t0 = 4 * j
addu $t4, $t0, $t6 # $t4 = array + 4*j, 即 $t4 = array[j]
lw $t3, 0($t4) # $t3 = array[j]
bge $t2, $t3, continue # if (a[j] >= a[j+1]) jump to the continue module
sw $t3, 0($t1) # else
sw $t2, 0($t4) # exchange a[j] with a[j+1]
continue:
# continue the "for" loop
# 实现 j < 10-i-1; j++
addi $t9, $t9, 1 # j++
move $t0, $t9 # $t0 = j
sub $t1, $t8, $t7 # $t1 = $t8 - i = 10 - i
sub $t1, $t1, 1 # $t1 = $t1 - 1 = 10 - i - 1
blt $t0, $t1, loop2 # if j < 10-i-1, jump to loop2
# 实现 i < 10-1; i++
addi $t7, $t7, 1 # i++
sub $t2, $t8, 1 # $t2 = $t8 - 1 = 10 - 1
blt $t7, $t2, loop1 # if i < 10 - 1, jump to loop1
output:
li $v0, 4 # 操作码$v0 = 4, 将要打印的字符串赋给 $a0
la $a0, output_msg # 打印字符串,提示用户即将输出程序
syscall
move $t7, $zero # 将变量置为0,用于下一循环,节省寄存器
print:
# 打印数组元素
move $t0, $t7 # $t0 = i
mul $t0, $t0, 4 # $t0 = 4 * i
addu $t1, $t0, $t6 # $t1 = array + 4*i, 即 $t1 = array[i]
li $v0, 1 # 操作码$v0 = 1, 将要打印的字整型赋给 $a0
lw $a0, 0($t1)
syscall
li $v0, 4 # 操作码$v0 = 4, 将要打印的字符串赋给 $a0
la $a0, space # 打印空格,分隔数组元素
syscall
addi $t7, $t7, 1 # i++
blt $t7, $t8, print # if i < 10, jump to print
.data # 数据声明,数据段以.data为开始标志
array:.space 1024 # .space指明空间大小, 单位为 bytes
input_msg:.asciiz "Please enter 10 numbers to be sorted, each number a single line:\n"
output_msg:.asciiz "The sorted numbers are:\n"
space:.asciiz " "
# 用双引号包含字符串
# 变量名后留冒号:
# .asciiz会在字符串最后加上一个终止符,类似C中的'\0', 而.ascii则不会
五.实验结果
Please enter 10 numbers to be sorted, each number a single line:
1
0
2
9
3
8
4
7
5
6
The sorted numbers are:
9 8 7 6 5 4 3 2 1 0
参考和学习了以下网站:
MIPS汇编:冒泡排序
计算机组成原理之MIPS汇编:冒泡排序
【十分钟教会你汇编】MIPS编程入门