[Hb-X] 课程设计I(寻址 数字转字符串 除法溢出 显示字符串)
来源:互联网 发布:如寡人者安与知耻的知 编辑:程序博客网 时间:2024/05/17 02:35
《汇编语言·第三版》--王爽
1 任务
将实验7中的Power idea公司的数据按照图10.2所示的格式在屏幕上显示出来。
在这个程序中,要用到前面学到的几乎所有的知识,主要选择适当的寻址方式和相关子程序的设计和应用。
另外,要注意,因为程序显示的数据有些已经大于65535,应该编写一个新的数据到字符串转化的子程序,完成dword型数据到字符串的转化,说明如下。
名称:dtoc
功能:将dword型数转变为表示十进制数的字符串,字符串以0为结尾符。
参数:(ax) = dword型数据的低16位,(dx) = dword型数据的高16位,ds:si指向字符串的首地址
返回:无
在这个子程序中要注意除法溢出的问题,可以用我们在实验IV中设计的子程序divdw来解决。
2 程序设计
(1) 程序流程图
Figure1. 程序设计图
divdw():解决“收入/员工”除法溢出问题,并得出员工平均工资。
dtoc():数字转字符串。
show_str():将Buf内以0结束的字符串以指定属性显示在指定的行列。
(2) 程序流程图对应的程序框架
1. assume cs:main,ss:stack
2.
3. ;数据段:存储欲显示在显存之上的数据
4. data segment
5. db '1975','1976','1977','1978','1979','1980','1981','1982','1983'
6. db '1984','1985','1986','1987','1988','1989','1990','1991','1992'
7. db '1993','1994','1995'
8. ;以上是表示21年的21个字符串
9.
10. dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
11. dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
12. ;以上是表示21年公司总收入的21个dword型数据
13.
14. dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
15. dw 11542,14430,15275,17800
16. ;以上是表示21年雇员人数的21个word型数据
17. data ends
18.
19. ;缓存区
20. buf segment
21. db 32 dup(0),0
22. buf ends
23.
24. ;堆栈段:(7 + 14 * 2)bytes足矣
25. stack segment
26. dw 20 dup(0)
27. stack ends
28.
29.
30. main segment
31. start:
32. main0:
33. call far ptr read_year ;调用read_year函数,将data段(si) + 1年份读到buf中,以0结束
34. call far ptr show_str ;调用show_str显示在buf中的字符串
35.
36.
37. call far ptr read_money ;调用read_money读si年的收入,将收入的低16位保存到ax中,收入的高16位保存到dx中
38. call far ptr dtoc ;调用dtoc将ax和dx共同保存的数据转换为对应的字符串到buf中
39. call far ptr show_str ;调用show_str显示在buf中的字符串
40.
41.
42. call far ptr read_staff ;调用read_staff读取data中的员工数目,(bx) =员工数目
43. call far ptr dtoc ;调用dtoc将ax和dx共同保存的数据转换为对应的字符串到buf中
44. call far ptr show_str ;调用show_str显示在buf中的字符串
45.
46.
47. call far ptr read_money ;调用read_money读si年的收入,将收入的低16位保存到ax中,收入的高16位保存到dx中
48. call far ptr read_staff ;调用read_staff读取data中si年的员工数目,(bx) =员工数目
49. call far ptr dtoc ;调用dtoc将ax和dx共同保存的数据转换为对应的字符串到buf中
50. call far ptr show_str ;调用show_str显示在buf中的字符串
51. loop main0
52.
53. mov ax, 4c00h
54. int 21h3 子函数
编写子函数时,各子函数要主要压栈保存在子函数内会修改的寄存器变量值。
(1) 数字转字符串
1. ;功能:将dword型数转变为表示十进制数的字符串,字符串以0为结尾符。
2. ;参数:(ax) = dword型数据的低16位,(dx) = dword型数据的高16位,ds:si指向字符串的首地址
3. ;返回:无
4. dtoc:
5. push ax
6. push cx
7. push dx
8. push si
9.
10. mov cx, 0
11. push cx ;先将0入栈,作为标记
12.
13. dtc_s0:
14. mov cx,ax
15. add cx,dx
16. jcxz dtc_s1
17. mov cx,10
18. call far ptr divdw
19. add cx,30h
20. push cx
21. loop dtc_s0
22.
23. dtc_s1:
24. pop cx
25. mov ds:[si],cl
26. jcxz dtc_s2
27. inc si
28. loop dtc_s1 ;将栈中数据取出
29.
30. dtc_s2:
31. pop si
32. pop dx
33. pop cx
34. pop ax
35. retf(2) 解决除法溢出问题
1. ;功能:进行不会产生溢出的除法运算,被除数为dword型,除数为word型,结果为dword型。
2. ;参数:(ax) = dword型数据的低16位,(dx) = dword型数据的高16位,(cx) = 除数
3. ;返回:(dx) = 结果的高16位,(ax) = 结果的低16位,(cx) = 余数
4. divdw:
5. push bx
6. push si
7.
8. mov bx,ax
9. mov ax, dx
10. mov dx, 0
11.
12. div cx ;ax = int(H/N), dx = rem(H/N)
13. mov si, ax ;si =int(H/N), (dx) = rem(H/N) * 65536
14.
15. mov ax, bx
16. div cx ;(rem(H/N) * 65536 + L) / N, ax保存的低16位商,(dx) = 余数
17.
18. mov cx, dx
19. mov dx, si
20.
21. pop si
22. pop bx
23. retf(3) 显示字符串
1. ;功能:在指定的位置,用指定的颜色,显示一个用0结束的字符串
2. ;参数:(dh) = 行号(取值范围 0 ~ 24),(dl) = 列号(取值范围0 ~ 79),(cl) = 颜色,ds:si指向字符串的首地址
3. ;返回:无
4. show_str:
5. push ax
6. push cx
7. push dx
8. push es
9. push bp
10. push di
11. push si
12.
13. mov ax, 0b800h
14. mov es, ax ;es段保存显存段地址
15.
16. mov al, cl ;字符前景色保存到al
17.
18. mov bp, 0
19. mov ch, 0
20. mov cl, dh
21. inc cl
22. str_s0:
23. jcxz str_s1
24. add bp,160 ;行号对应的显存地址
25. loop str_s0
26. str_s1:
27. mov di,0
28. mov ch,0
29. mov cl,dl
30. str_s2:
31. jcxz str_s3
32. add di,2 ;列号对应的显存地址
33. loop str_s2 ;es:[di + bp]为dh行dl列对应的显存地址
34.
35. str_s3:
36. mov cl,ds:[si]
37. jcxz str_s4 ;检测当前字符是否为0,如果为0则转移到s4处执行
38. mov es:[bp+ di],cl
39. inc di
40. mov es:[bp+di], al ;字符前景色
41. inc di
42. inc si
43. loop str_s3
44.
45. str_s4:
46. pop si
47. pop di
48. pop bp
49. pop es
50. pop dx
51. pop cx
52. pop ax
53. retf(4) 用来读(寻址)data段数据的子函数
1. ;功能:读取data段的(si)年份到buf中,以0结束
2. ;参数:无
3. ;返回:无
4. read_year:
5. push ax
6. push cx
7. push dx
8. push ds
9. push si
10. push bp
11.
12. mov ax, data
13. mov ds, ax
14. mov ax, 4
15. mul si
16. mov si, ax ;ds:[si]指向pop si,(si)年的年份
17.
18. mov ax, buf
19. mov es,ax
20. mov bp, 0 ;es:[bp]指向buf段的首个内存单元
21.
22. mov cx, 2
23. read_s0:
24. mov ax,ds:[si]
25. mov es:[bp],ax ;年份低字节
26. add si,2
27. add bp,2
28. loop read_s0
29.
30. mov al, 0
31. mov es:[bp],al ;字符串以0为结尾符
32.
33. pop bp
34. pop si
35. pop ds
36. pop dx
37. pop cx
38. pop ax
39. Retf
40.
41.
42. ;功能:读取data段的(si)年收入到(ax)和(dx)中
43. 参数:(si) = 第几年
44. ;返回:(ax) = dword低16位,(dx)=dword高16位
45. read_money:
46. push si
47. push ds
48.
49. mov ax, data
50. mov ds, ax
51. mov ax, 4
52. mul si
53. mov si, ax
54. add si, 84 ;ds:[si]指向pop si年的收入
55.
56. mov ax,ds:[si]
57. mov dx,ds:[si + 2]
58.
59. pop ds
60. pop si
61. Retf
62.
63.
64.
65. ;功能:读取data段的(si)年员工数到(ax)中
66. ;参数:(si) = 第几年
67. ;返回:(ax) = 员工数
68. read_staff:
69. push ax
70. push dx ;乘法会改变dx的值
71. push si
72. push ds
73.
74. mov ax, data
75. mov ds, ax
76. mov ax, 2
77. mul si
78. mov si, ax
79. add si, 168 ;ds:[si]指向pop si年的员工
80.
81. mov bx,ds:[si]
82.
83. pop ds
84. pop si
85. pop dx
86. pop ax
87. retf4 主程序
1. main segment
2. start: mov ax, stack
3. mov ss, ax
4. mov sp, 40 ;ss:sp指向栈底
5.
6. mov cx, 21 ;每次读一年数据,一共21年的数据,需要读21次
7. mov si, 0 ;用来表示将要读取第(si) + 1年的数据
8. mov dx, 02h ;第一年数据第一个数据在屏幕上显示的位置
9.
10. main_s1_3:
11. ;---------------显示年份--------------------------------------------
12. call far ptr read_year ;调用read_year函数,将data段(si) + 1年份读到buf中,以0结束
13.
14. push cx
15. push si ;需要压栈保存寄存器的值
16. mov ax, buf
17. mov ds, ax
18. mov si, 0
19. mov cl, 02
20. call far ptr show_str ;调用show_str显示在buf中的字符串
21. ;---------------显示年份--------------------------------------------
22.
23. ;---------------显示收入--------------------------------------------
24. pop si ;需要出栈使用寄存器的值
25. push si
26. push dx
27. call far ptr read_money ;调用read_money读si年的收入,将收入的低16位保存到ax中,收入的高16位保存到dx中
28. mov bx, buf
29. mov ds, bx
30. mov si, 0
31. call far ptr dtoc ;调用dtoc将ax和dx共同保存的数据转换为对应的字符串到buf中
32.
33. pop dx
34. push dx
35. mov ax, buf
36. mov ds, ax
37. mov si, 0
38. add dl, 12
39. mov cl, 2
40. call far ptr show_str ;调用show_str显示在buf中的字符串
41. pop dx
42. ;---------------显示收入--------------------------------------------
43.
44. ;---------------显示员工--------------------------------------------
45. pop si
46. push si
47. push dx
48. call far ptr read_staff ;调用read_staff读取data中的员工数目,(bx) =员工数目
49. mov ax, bx
50. mov dx, 0
51. mov bx, buf
52. mov ds, bx
53. mov si, 0
54. call far ptr dtoc ;调用dtoc将ax和dx共同保存的数据转换为对应的字符串到buf中
55.
56. pop dx
57.
58. push dx
59. mov ax, buf
60. mov ds, ax
61. mov si, 0
62. add dl, 24
63. call far ptr show_str ;调用show_str显示在buf中的字符串
64. pop dx
65. pop si
66.
67.
68. inc si ;下一年数据
69. inc dh ;显示在下一行
70.
71. pop cx
72. loop main_s1_3
73. ;---------------显示员工--------------------------------------------
74.
75. ;---------------显示员工平均工资--------------------------------------------
76.
77. mov cx, 21 ;每次读一年数据,一共21年的数据,需要读21次
78. mov si, 0 ;用来表示将要读取第(si) + 1年的数据
79. mov dx, 02h ;第一年数据第一个数据在屏幕上显示的位置
80. main_s4:
81. push cx
82. push dx
83. call far ptr read_money ;调用read_money读si年的收入,将收入的低16位保存到ax中,收入的高16位保存到dx中
84. call far ptr read_staff ;调用read_staff读取data中si年的员工数目,(bx) =员工数目
85. mov cx, bx
86. call far ptr divdw
87.
88. push si
89. mov bx, buf
90. mov ds, bx
91. mov si, 0
92. call far ptr dtoc ;调用dtoc将ax和dx共同保存的数据转换为对应的字符串到buf中
93. pop si
94.
95. pop dx
96. push si
97. push dx
98. mov ax, buf
99. mov ds, ax
100. mov si, 0
101. add dl, 34
102. mov cl, 2
103. call far ptr show_str ;调用show_str显示在buf中的字符串
104. ;---------------显示员工平均工资--------------------------------------------
105. pop dx
106. pop si
107.
108. inc si ;下一年数据
109. inc dh ;显示在下一行
110.
111. pop cx
112. loop main_s4
113.
114. mov ax, 4c00h
115. int 21h
116.
117. ;子函数定义区
118.
119. main ends
120. end start5 运行结果
- [Hb-X] 课程设计I(寻址 数字转字符串 除法溢出 显示字符串)
- [Hb-IX] 编写子程序(显示字符串、数值,除法溢出问题)
- [Hb-VIII] 转移指令 显示带色字符串
- 将数字字符串转化为对应数字输出(不考虑溢出)
- 子字符串寻址
- 子字符串寻址
- 数字转字符串(改)
- 微机原理课程设计32位汇编学习之三(显示字符串)
- 微机原理课程设计32位汇编学习之四(显示字符串之特殊字体)
- java字符串除法
- jqgrid格式化字符串(整型、数字、货币、日期、显示连接)
- java数字转字符串
- 数字转字符串
- 数字字符串转整数
- 字符串转整型数字
- 数字转字符串
- 数字转罗马字符串
- 数字转字符串
- nginx haproxy两者做负载均衡的优缺点
- While reading XXX pngcrush caught libpng error
- 处理字符串 去除空格
- Android两次后退键退出
- Android手机目前常见的分辨率
- [Hb-X] 课程设计I(寻址 数字转字符串 除法溢出 显示字符串)
- 苹果apns推送总结
- 16周课后自主-项目4-动态数组
- Java包装类
- Valid Palindrome
- DB2错误码汇总
- 点到圆的最近距离公式推导
- 问题列表
- 移植tcpdump到arm linux