设计思想

  1. 由题意,可输入一串字符串,含有需要排序的数据,设计一个change1函数,将字符串中的数字字符提取出来作为整数存入另一个数组空间内。

  2. 转换完成后,编写函数output1,输出存入数组的数据个数和未排序的整型数组。

  3. 编写done函数,进行数组的选择排序,包含内外两循环,每次比较时,将较小的数放到前面。

  4. 再次调用output1函数,可输出排序后的数组。

  5. 最后退出程序。

流程图

1.png

开发环境

Windows平台+Mars环境

程序源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
#程序功能描述:

#输入数字字串并转为整型数据存储

#显示数字个数和输入的整数

#排序(递增)后输出最终结果

###########################################################

#函数描述:

#change1: 将字符串转换为数值并储存

#output1: 输出转换后的数值数组

#done: 将数组进行排序(递增)

###########################################################

.data

start: .asciiz "Input Numbers: \n" #输入提示串

output_1: .asciiz "The num of all is: " #数组大小

output_2: .asciiz "\n The detail:\n" #数组详细数值

empty: .asciiz " " #空格

output_3: .asciiz "\n The detail after sort is:\n" #排序后的数组数据

num: .word 0

.space 1024 #定义一个整型数组及大小

string: .space 1024 #定义字符串数组及大小

.globl main

.text

main: la $a0,start

​ li $v0,4

​ syscall #初始提示串

​ la $a0,string

​ li $a1,1024

​ li $v0,8

​ syscall #输入字符串

​ move $t0,$a0

​ li $s0,0x20 #空格

​ li $s1,0x0a #换行

​ la $a0,num #数组初地址

​ move $t1,$a0

​ li $a0,0

​ li $t2,0

​ addi $sp,$sp,-12

​ sw $t1,0($sp)

​ sw $t0,4($sp)

​ sw $ra,8($sp) #利用栈保护相关数值

​ jal change1 #将字符串转换为数值并储存

​ lw $ra,8($sp)

​ lw $t0,4($sp)

​ lw $t1,0($sp)

​ addi $sp,$sp,12 #恢复

​ la $a0,output_1

​ li $v0,4

​ syscall

​ move $a0,$t2

​ li $v0,1

​ syscall

​ la $a0,output_2 #输出提示串

​ li $v0,4

​ syscall

​ addi $sp,$sp,-12

​ sw $t1,0($sp)

​ sw $t2,4($sp)

​ sw $ra,8($sp)

​ jal output1 #输出转换后的数值数组

​ lw $ra,8($sp)

​ lw $t2,4($sp)

​ lw $t1,0($sp)

​ addi $sp,$sp,12

​ addi $sp,$sp,-12

​ sw $t2,0($sp) #数组大小

​ sw $t1,4($sp) #数组初地址

​ sw $ra,8($sp)

​ jal done #调用排序函数

​ lw $ra,8($sp)

​ lw $t1,4($sp)

​ lw $t2,0($sp)

​ addi $sp,$sp,12

​ la $a0,output_3 #输出提示

​ li $v0,4

​ syscall

​ jal output1 #输出排序后的数组

​ li $v0,10 #退出

​ syscall

loop0: sw $a0,($t1) #存入整型数组

​ addi $t1,$t1,4 #整型数组地址加4

​ addi $t2,$t2,1 #记录数组大小

​ addi $t0,$t0,1 #字符串地址加1

​ li $a0,0

change1: lb $a3,($t0) #取一个字节

​ beq $a3,$s0,loop0 #为空格则到loop0

​ beq $a3,$s1,ret1 #为回车则到ret1

​ beqz $a3,ret #为0则到ret

​ mul $a0,$a0,10

​ addi $a2,$a3,-48 #字符转换

​ addu $a0,$a0,$a2

​ addi $t0,$t0,1 #地址加一

​ b change1

done: la $a0, num #a0=num首地址

​ addi $t0,$t2,-1 #外循环变量t0初始化为数组长度-1

lp0: addi $a1, $a0, 4 #外循环起点。内循环的起始比较单元初始化

​ addi $t1, $t0,-1 #内循环变量t1初始化,t1=t0-1

lp1: lw $t2, ($a0) #内循环起点。取出本趟比较的单元

​ lw $t3, ($a1) #逐个取出随后的单元

​ ble $t2, $t3, next #前面的小,则什么都不做

​ sw $t2, ($a1) #前面的大,则交换2个单元

​ sw $t3, ($a0)

next: addi $a1, $a1, 4 #a1指向下一个单元

​ addi $t1, $t1,-1 #内循环变量t1--

​ bgez $t1,lp1 #内循环结束,直到t1=0退出循环

​ addi $a0, $a0, 4 #准备下一轮,a1指向下一轮比较的单元

​ addi $t0, $t0,-1 #外循环变量t0--

​ bgt $t0, $0, lp0 #外循环结束,直到t0=0退出循环

​ j ret # 返回

output1: beqz $t2,ret #控制条件

​ lw $a0,($t1)

​ li $v0,1 #输出数组元素

​ syscall

​ addi $t2,$t2,-1

​ addi $t1,$t1,4

​ la $a0,empty #空格

​ li $v0,4

​ syscall

​ b output1

ret1: sw $a0,($t1)

​ addi $t2,$t2,1

​ jr $ra #存储并返回

ret: jr $ra #返回

测试过程

​ 编写完代码后,初测试,发现编译通过,运行错误,经过逐步运行排查,发现change1函数处的lw指令发生错误,分析后发现该处字符串中的取字符应该用lb进行取字符而不能用lwlw是对字的取值,lb是对字节单位的取值,改完代码后发现程序运行正常,问题排除。

结果

2.png

3.png

4.png

5.png

6.png

写在最后

​ 编写这道题时,首先理清思路,输入一段字符串,然后用函数将字符串进行转换,遇到空格或换行符存储一个数,要注意lwlb的用法,前者是取字(4个字节),后者是取字节(1个字节),对字符串的字符要用lb,而用lw就会导致程序运行出错。然后使用选择排序函数进行排序,每两个数比较,将较小的数放到越前面,内外循环依次遍历,循环结束后,将排序后的数组输出。

​ 因为涉及函数及变量较多,所以使用了栈保护相关寄存器内的值,要注意$sp的合理使用和使用后的恢复,合理使用能够保证相关寄存器的值在调用前后不改变,实现程序的合理运行,达到预期的效果。