1. DATAS SEGMENT
2. ;此处输入数据段代码
3. string_main db 'plase input the function number (1~5)$'
4. tip DB 'please input string:','$'
5. string_task2_result2 db 'The maximum is :$'
6. string_error db 'Wrong number, please input again. $'
7. string_task3_info db 'please input the DECimAL numbers:',0DH,0AH,'$'
8. again_or_return db 'What do you want to do next" Main Menu or Redo"[ESC/any other key]: $'
9. task1_info db 'Now, we are doing fuction 1: $'
10. task2_info db 'Now, we are doing fuction 2: $'
11. task3_info db 'Now, we are doing fuction 3: $'
12. ; emu8086不支持dup(?) 因此用0来初始化
13. string_task1 db 100 dup(0)
14. string_task1_result db 100 dup(0)
15. string_task2 db 100 dup(0)
16. string_task2_result db 10 dup(0)
17. string_task3 db 100 dup(0)
18. string_task3_count db 10 dup(0)
19. string_task3_result db 100 dup(0)
20. hour db 0
21. minute db 0
22. second db 0
23. time db "00:00:00$"
24. len equ $-time
25. num db 0
26.
27. DATAS ENDS
28.
29. STACKS SEGMENT
30. TOP LABEL WORD
31. ;此处输入堆栈段代码
32. DW 100H DUP(0)
33. STACKS ENDS
34.
35. ;换行
36. print_line macro
37. MOV AH,2 ;调用2号功能系统,将DL的内容显示到屏幕
38. MOV DL,0DH ;0DH是回车符的ASCII码
39. INT 21h
40. MOV AH,2
41. MOV DL,0AH ;0AH是换行符的ASCII码
42. INT 21h
43. endm
44.
45. ;调用DOS功能,该功能为显示DS:DX地址处的字符
46. print_string macro string
47. LEA DX,string
48. MOV AH,09h
49. INT 21h
50. endm
51.
52. ;用来获取单个输入字符
53. get_char macro
54. MOV AH,1
55. INT 21h
56. endm
57.
58. CODES SEGMENT
59. ASSUME CS:CODES,DS:DATAS,SS:STACKS
60. START:
61. MOV AX,DATAS
62. MOV DS,AX
63.
64. menu:
65. print_string string_main
66. get_char
67. ;只能输入1-5
68. CMP AL,31h
69. JB main_input_error
70. CMP AL,35h
71. JA main_input_error
72. JMP select
73.
74. main_input_error:
75. print_line
76. print_string string_error
77. print_line
78. JMP menu
79.
80. select:
81. CMP AL,31h
82. JE Task1
83. CMP AL,32h
84. JE Task2
85. CMP AL,33h
86. JE Task3
87. CMP AL,34h
88. JE Task4
89. CMP AL,35h
90. JE Task5
91.
92. return_menu:
93. print_line
94. JMP menu
95.
96. ;任务一:实现小写转化成大写
97. Task1 PROC
98. print_line
99. print_line
100. print_string task1_info
101. print_line
102. print_string tip
103. LEA SI,string_task1
104. MOV CL,00H;CL用来存储需要处理字符的数量,初始化置0
105.
106. restore_input:
107. get_char
108. MOV BL,AL ;BL用来存储输入的字符信息,保护数据
109. ;假如当前字符输入是回车(0DH),则不进行存储,直接跳出
110. CMP AL,0DH
111. JE deal_first
112. ;对空格字符进行存储,单独判断
113. CMP AL,20H ;20H为"空格"的ASCII码
114. JE real_store
115. ;设置输入字符的范围,只能存储数字、大小写字母,否则报错
116. CMP AL,30H ;30H为"0"的ASCII码
117. JB input_error
118. CMP AL,39H ;39H为"9"的ASCII码
119. JBE real_store
120. CMP AL,41H ;41H为"A"的ASCII码
121. JB input_error
122. CMP AL,5AH ;5AH为"Z"的ASCII码
123. JBE real_store
124. CMP AL,61H ;61H为"a"的ASCII码
125. JB input_error
126. CMP AL,7AH ;7AH为"z"的ASCII码
127. JBE real_store
128.
129. ;错误跳转信息,并重新提示输入
130. input_error:
131. print_line
132. print_string string_error
133. print_line
134. print_string tip
135. LEA SI,string_task1
136. MOV CL,00H;CL用来存储需要处理字符的数量,初始化置0
137. JMP restore_input
138.
139. ;存储当前字符
140. real_store:
141. MOV AL,BL ;将BL存储的字符重新赋值给AL
142. MOV [SI],AL ;将AL存储的字符传输到[SI]进行存储
143. INC SI
144. INC CL
145. INC DI
146. ;未检测到结束标志“回车”,返回上一步继续存储下一个字符
147. JMP restore_input
148.
149. ;重新回到存储的首地址位置,对每一个字符进行处理
150. deal_first:
151. LEA SI,string_task1
152. LEA DI,string_task1_result
153.
154. cmp_data:
155. ;CL用来记录剩余的处理字符数量,若CL无空值,直接跳出
156. CMP CL,00h
157. JE task1_finish
158. MOV AL,[SI]
159. ;只有小写字母才进行转换,若不是小写字母直接输出
160. CMP AL,61h
161. JB cmp_data_finish
162. SUB AL,20h ;小写转大写:小写字母-20H
163.
164. cmp_data_finish:
165. ;[DI]用来存储处理后的字符数据
166. MOV [DI],AL
167. INC SI
168. DEC CL ;处理完一个字符,CL-1
169. INC DI
170. ;CL不为0,代表没处理完
171. JMP cmp_data
172.
173. task1_finish:
174. print_line
175. ;为输入和输出字符串添加结束标志
176. MOV [SI],'$'
177. MOV [DI],'$'
178. ;这里显示输入
179. print_string string_task1
180. print_line
181. ;这里显示输出结果
182. print_string string_task1_result
183. print_line
184.
185. ;判断返回菜单或者重试
186. print_string again_or_return
187. get_char
188. CMP AL,1BH ;判断是否按下esc
189. JE return_menu
190.
191. JMP Task1
192.
193. Task1 ENDP
194.
195. ;任务二:在字符中找最大值
196. Task2 PROC
197. print_line
198. print_line
199. print_string task2_info
200. print_line
201. print_string tip
202. LEA SI,string_task2
203. MOV CL,00H;CL用来存储需要处理字符的数量,初始化置0
204.
205. task_2_restore_input:
206. get_char
207. MOV BL,AL ;BL用来存储输入的字符信息,保护数据
208. ;假如当前字符输入是回车(0DH),则不进行存储,直接跳出
209. CMP AL,0DH
210. JE task2_dealfirst
211.
212. ;设置输入字符的范围,只能存储数字、大小写字母,否则报错
213. CMP AL,30H ;30H为"0"的ASCII码
214. JB task2_input_error
215. CMP AL,39H ;39H为"9"的ASCII码
216. JBE task2_store
217. CMP AL,41H ;41H为"A"的ASCII码
218. JB task2_input_error
219. CMP AL,5AH ;5AH为"Z"的ASCII码
220. JBE task2_store
221. CMP AL,61H ;61H为"a"的ASCII码
222. JB task2_input_error
223. CMP AL,7AH ;7AH为"z"的ASCII码
224. JBE task2_store
225.
226. task2_store:
227. MOV AL,BL
228. MOV [SI],AL
229. INC SI
230. INC CL
231. JMP task_2_restore_input
232.
233. ;错误跳转信息,并重新提示输入
234. task2_input_error:
235. print_line
236. print_string string_error
237. print_line
238. print_string tip
239. JMP Task2
240.
241. task2_dealfirst:
242. LEA SI,string_task2
243. LEA DI,string_task2_result
244. MOV AL,[SI]
245. MOV [DI],AL ;[DI]用来存储输入的数据
246. INC SI
247. DEC CL
248.
249. ;遍历比较
250. func_2_cmp_data:
251. ;假如已经遍历完毕则进行跳出
252. CMP CL,00h
253. JE func2_finish
254. MOV AL,[SI]
255. MOV AH,[DI]
256. ;假如AL>AH,进行跳转,将AL的值存入[DI],即最大值
257. CMP AL,AH
258. JA func_2_cmp_data_finish ;JA:无符号大于则跳转
259. INC SI
260. DEC CL
261. JMP func_2_cmp_data
262.
263. func_2_cmp_data_finish:
264. MOV [DI],AL
265. INC SI
266. DEC CL
267. JMP func_2_cmp_data
268.
269. func2_finish:
270. print_line
271. MOV [SI],'$'
272. INC DI
273. MOV [DI],'$'
274. ;先输出原字符串
275. print_string string_task2
276. ;补一个空格进行分隔
277. MOV DL,20h
278. MOV AH,2
279. INT 21H
280. print_string string_task2_result2 ;the maximum is :$
281. print_string string_task2_result
282. print_line
283.
284. ;判断返回菜单或者重试
285. print_string again_or_return
286. get_char
287. CMP AL,1BH ;判断是否按下esc
288. JE return_menu
289.
290. JMP Task2
291.
292. Task2 ENDP
293.
294. ;任务三:输入数据组的排序
295. Task3 PROC
296. print_line
297. print_line
298. print_string task3_info
299. print_line
300. print_string string_task3_info
301. LEA SI,string_task3
302. MOV CL,0
303. MOV BH,0
304. MOV DI,0
305.
306. task3_store:
307. MOV DL,0
308. MOV DH,10
309.
310. task_3_real_store:
311. get_char
312. CMP AL,0DH ;判断是否按下回车键
313. JE task3_next_step
314. CMP AL,20H ;判断是否按下空格键
315. JE task3_save_num
316. ;小于0或大于9跳转报错
317. CMP AL,30H ;30H为"0"的ASCII码
318. JB task3_error_input
319. CMP AL,39H ;39H为"9"的ASCII码
320. JA task3_error_input
321. MOV BH,0
322. ;这里首先需要将ASCII码转换成十进制数,0的ASCII码为30H,因此可以用ASCII码-30H或者将高位清零
323. AND AL,0FH ;高4位清零
324. MOV BL,AL
325. MOV AL,DL
326. MUL DH ;每一个高位*10
327. ADD AX,BX
328. MOV DL,AL
329. JMP task_3_real_store
330.
331. task3_error_input:
332. print_line
333. print_string string_error
334. JMP Task3
335.
336. ;检测到空格则进行一次数值保存
337. task3_save_num:
338. CMP BH,0
339. JNZ task3_before_store
340. MOV [SI],DL
341. INC SI
342. INC CL
343.
344. task3_before_store:
345. MOV BH,1
346. JMP task3_store
347.
348. ;输出回车之后
349. task3_next_step:
350. ;注意,换行会改变DL数值,因此必须用堆栈保护DL,栈仅能对字节进行操作
351. PUSH DX
352. print_line
353. POP DX
354. MOV [SI],DL
355. INC SI
356. INC CL
357. LEA DI,string_task3_count
358. MOV [DI],CL
359.
360. task3_finish:
361. LEA DI,string_task3_count
362. MOV CL,[DI]
363.
364. LEA DI,string_task3
365. PUSH DX
366. print_line
367. POP DX
368.
369. ;将十六进制数转换成ASCII码显示输出
370. task3_write:
371. MOV BH,[DI]
372. MOV DL,BH
373. AND DL,0F0H ;低位清零
374. SHR DL,4 ;逻辑右移,将DL右移4位
375. CMP DL,0AH
376. JGE task3_writehighchar
377. ADD DL,30H ;数值0-9要进行显示需转换成ASCII码,需+30H
378. JMP task3_writehigh
379.
380. ;用来写当前十六进制数的高位
381. task3_writehighchar:
382. ADD DL,37H ;数值A-F要进行显示需转换成ASCII码,需+37H
383.
384. task3_writehigh:
385. MOV AH,2
386. INT 21H
387. MOV DL,BH
388. AND DL,00FH ;高位清零
389. CMP DL,0AH
390. JGE task3_writelowchar ;JGE大于等于
391. ADD DL,30H
392. JMP task3_writelow
393.
394. ;写当前十六进制数的低位
395. task3_writelowchar:
396. ADD DL,37H
397.
398. task3_writelow:
399.
400. MOV AH,2
401. INT 21H
402. ;每输出一个十六进制数在后面添加H标识
403. MOV DL,48H
404. MOV AH,2
405. INT 21H
406. ;每输出一个十六进制数显示空格进行分隔
407. MOV DL,20h
408. MOV AH,2
409. INT 21H
410.
411. INC DI
412. DEC CL
413. CMP CL,0 ;CL记录剩余处理的字符数量,假如不为0,继续跳转运行
414. JNE task3_write
415.
416. ;采用选择排序实现十六进制从小到大输出
417. ;BL用来存储第i位,BH用来存储第i+1,i+2,i+3...位,每次外循环确定第i位最小值
418. sort:
419. LEA SI,string_task3_count
420. MOV CL,[SI]
421. LEA SI,string_task3
422.
423. ;外循环
424. fori:
425. LEA DI,string_task3_count
426. MOV CH,CL
427. MOV DI,SI
428. INC DI
429. ;内循环
430. forj:
431. MOV BL,[SI]
432. MOV BH,[DI]
433. CMP BL,BH
434. JBE afterswap
435. MOV [SI],BH
436. MOV [DI],BL
437.
438. afterswap:
439. DEC CH
440. INC DI
441. CMP CH,1
442. JA forj
443.
444. INC SI
445. DEC CL
446. CMP CL,1
447. JA fori
448.
449. task3_finish2:
450. LEA DI,string_task3_count
451. MOV CL,[DI]
452. LEA DI,string_task3
453. PUSH DX
454. print_line
455. POP DX
456.
457. ;输出排序后的结果
458. task3_write2:
459. MOV BH,[DI]
460. MOV DL,BH
461. AND DL,0F0H ;低位清零
462. SHR DL,4 ;逻辑右移,将DL右移4位
463. CMP DL,0AH
464. JGE task3_writehighchar2
465. ADD DL,30H ;数值0-9要进行显示需转换成ASCII码,需+30H
466. JMP task3_writehigh2
467.
468. task3_writehighchar2:
469. ADD DL,37H ;数值A-F要进行显示需转换成ASCII码,需+37H
470.
471. task3_writehigh2:
472. MOV AH,2
473. INT 21H
474. MOV DL,BH
475. AND DL,00FH ;高位清零
476. CMP DL,0AH
477. JGE task3_writelowchar2 ;JGE大于等于
478. ADD DL,30H
479. JMP task3_writelow2
480.
481. ;写当前十六进制数的低位
482. task3_writelowchar2:
483. ADD DL,37H
484.
485. task3_writelow2:
486. MOV AH,2
487. INT 21H
488. ;每输出一个十六进制数在后面添加H标识
489. MOV DL,48H
490. MOV AH,2
491. INT 21H
492. ;每输出一个十六进制数显示空格进行分隔
493. MOV DL,20h
494. MOV AH,2
495. INT 21H
496. INC DI
497. DEC CL
498. CMP CL,0 ;CL记录剩余处理的字符数量,假如不为0,继续跳转运行
499. JNE task3_write2
500.
501. PUSH DX
502. print_line
503. POP DX
504. ;判断返回菜单或者重试
505. print_string again_or_return
506. get_char
507. CMP AL,1BH ;判断是否按下esc
508. JE return_menu
509.
510. JMP Task3
511.
512. Task3 ENDP
513.
514.
515. ;任务四:输出系统时间到屏幕右上角
516. Task4 PROC
517. ;首先对窗口清屏
518. clear:
519. MOV AX,CS
520. MOV SS,AX
521. MOV SP,0x7c00 ;set stack and SP
522.
523. MOV AH,0x06
524. MOV AL,0
525.
526. MOV CH,0 ;(0,0)
527. MOV CL,0
528. MOV DH,24 ;(24,79)
529. MOV DL,79
530. MOV BH,0x07 ;黑底白字
531. INT 0x10
532.
533. ;设置光标位置
534. setshow:
535. MOV DH,0 ;行号
536. MOV DL,72 ;列号
537. MOV BH,0
538. ;置光标位置
539. MOV AH,2
540. INT 10h
541.
542. ;获取系统时间
543. get_system_time:
544. ;获取时间
545. MOV AH,2Ch ;CH=时,CL=分,DH=秒
546. INT 21h
547. MOV hour,CH
548. MOV minute,CL
549. MOV second,DH
550. ;时间显示到字符串
551. MOV AX,0
552. MOV AL,hour ;商:AL,余数:AH
553. MOV num,10
554. DIV num
555. ADD AL,30h
556. MOV time[0],AL
557. ADD AH,30h
558. MOV time[1],AH
559.
560. MOV AX,0
561. MOV AL,minute
562. MOV num,10
563. DIV num
564. ADD AL,30h
565. MOV time[3],AL
566. ADD AH,30h
567. MOV time[4],AH
568.
569. MOV AX,0
570. MOV AL,second
571. MOV num,10
572. DIV num
573. ADD AL,30h
574. MOV time[6],AL
575. ADD AH,30h
576. MOV time[7],AH
577.
578. ;输出系统时间
579. LEA DX, time
580. MOV AH, 9
581. INT 21h
582.
583. ;判断返回菜单或者重试
584. print_string again_or_return
585. get_char
586. CMP AL,1BH ;判断是否按下esc
587. JE return_menu
588.
589. JMP setshow
590.
591. Task4 ENDP
592.
593.
594. ;任务五:退出
595. Task5 PROC
596. MOV AH, 4CH
597. INT 21h
598. Task5 ENDP
599.
600. CODES ENDS
601.