汇编语言(王爽第三版)实验七
实验七
题目
Power idea公司从1975年成立一直到1995年的基本情况如下。
| 年份 | 收入(千美元) | 雇员(人) | 人均收入(千美元) |
|---|---|---|---|
| 1975 | 16 | 3 | ? |
| 1976 | 22 | 3 | ? |
| 1977 | 382 | 3 | ? |
| 1978 | 1356 | 3 | ? |
| 1979 | 2390 | 3 | ? |
| 1980 | 8000 | 3 | ? |
| ┇ | |||
| 1995 | 5937000 | 17800 | ? |
| 下面的程序中,已经定义好了这些数据: |
assume cs:codesgdata segmentdb '1975','1976','1977','1978','1979','1980','1981','1982','1983'db '1984','1985','1986','1987','1988','1989','1990','1991','1992'db '1993','1994','1995';以上是表示21年的21个字符串dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000;以上是表示21年公司总收入的21个dword型数据dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226dw 11542,14430,15257,17800;以上是表示21年公司雇员人数的21个word型数据data endstable segmentdb 21 dup('year summ ne ?? ')
table ends end start
编程,将data段中的数据按如下格式写入到table段中,并计算21年中的人均收入(取整),结果也按照下面的格式保存在table段中。

思路
先确定一下数据的存放地址。
data段:
年份的数据占了21*4=84=54H。" db ‘1975’ “相当于"db 31H 39H 37H 35H”,“1”、“9”、“7”、"5"的ASCII码分别为31H 39H 37H 35H。
收入的数据占了21*4=84=54H。dword(双字节)型数据占4个字节32位。
雇员的数据占了21*2=42=2AH。word型数据占2个字节16位
由此可知,年份是0H~53H,收入是54H~A7H,雇员是A8H~D1H。
且有以下关系:
- data段地址+84(年份所占字节)=收入的数据起始地址
- data段地址+168(年份所占自己+收入所占字节)=雇员的数据起始地址
data段的数据占了DFH个字符,所以table段从E0H开始
如下图所示:

最暴力的方法就是4个循环21次分别把年份,收入,雇员数,人均收入存入table段中,刚开始想着能不能只循环一个21次就把所有数据插入table段中,结果发现似乎不太行。但是可以把年份和收入放在同一个循环中,然后雇员放在一个循环,平均收入放在一个循环,三个循环就解决了。
注意到年份和收入都是四字节,也就是他们可以同时使用一个增量di。由题目给的图可以知道数据要放在table段中的哪些位置。
程序如下:
assume cs:codesgdata segmentdb '1975','1976','1977','1978','1979','1980','1981','1982','1983'db '1984','1985','1986','1987','1988','1989','1990','1991','1992'db '1993','1994','1995';以上是表示21年的21个字符串dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000;以上是表示21年公司总收入的21个dword型数据dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226dw 11542,14430,15257,17800;以上是表示21年公司雇员人数的21个word型数据data endstable segmentdb 21 dup('year summ ne ?? ')
table ends codesg segmentstart:mov ax,datamov ds,axmov ax,tablemov es,axsub bx,bxsub di,dimov cx,21dateIncome:mov ax,ds:[di] ;年的前2个字节mov es:[bx],ax mov ax,ds:[di+84] ;收入的前2个字节mov es:[bx+5],axadd di,2mov ax,ds:[di] ;年的后2个字节mov es:[bx+2],ax mov ax,ds:[di+84] ;收入的后两个字节mov es:[bx+7],axadd di,2add bx,16loop dateIncomemov cx,21sub bx,bxsub di,dig: ;雇员mov ax,ds:[di+168]mov es:[bx+10],axadd di,2add bx,16loop gAvemov cx,21sub bx,bxsub di,disub si,siave:mov ax,ds:[di+84] ;收入低16位mov dx,ds:[di+84+2] ;收入高16位div word ptr ds:[si+168] ;雇员数mov es:[bx+13],ax ;商放axadd di,4add si,2add bx,16loop avemov ax,4c00Hint 21Hcodesg endsend start
运行结果如下

改进
可以发现雇员和收入都是两个字节,考虑一下两者是否可以结合。整体上来看即从三个21次循环改为二个21次循环。
如下图所示,相同颜色的都可以整合:

整合如下:

程序如下:
assume cs:codesgdata segmentdb '1975','1976','1977','1978','1979','1980','1981','1982','1983'db '1984','1985','1986','1987','1988','1989','1990','1991','1992'db '1993','1994','1995';以上是表示21年的21个字符串dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000;以上是表示21年公司总收入的21个dword型数据dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226dw 11542,14430,15257,17800;以上是表示21年公司雇员人数的21个word型数据data endstable segmentdb 21 dup('year summ ne ?? ')
table ends codesg segmentstart:mov ax,datamov ds,axmov ax,tablemov es,axsub bx,bxsub di,dimov cx,21dateIncome: ;处理年份和收入mov ax,ds:[di] ;年份的前2个字节mov es:[bx],ax mov ax,ds:[di+84] ;收入的前2个字节mov es:[bx+5],axadd di,2mov ax,ds:[di] ;年份的后2个字节mov es:[bx+2],ax mov ax,ds:[di+84] ;收入的后两个字节mov es:[bx+7],axadd di,2add bx,16loop dateIncomemov cx,21sub bx,bxsub di,disub si,sigAve: ;处理雇员和平均收入mov dx,ds:[si+168] ;雇员的全部字节mov es:[bx+10],dxmov ax,ds:[di+84] ;收入的前两个字节mov dx,ds:[di+84+2] ;收入的后两个字节div word ptr ds:[si+168]mov es:[bx+13],axadd di,4add si,2add bx,16loop gAvemov ax,4c00Hint 21Hcodesg endsend start
再改进
上面的改进已经把三个21次循环改为两个21次循环。在观察一下看看能不能把程序改进为在一个21次循环里就把所有数据插入table段中。
如下图所示:

改进成:

发现还可以在改进,即直接用[bx+2]来获取年份的后两个字节,[di+84+2]来获取收入的后两个字节。
如下所示:

改进后的代码更加容易阅读。
完整代码如下:
完整版
assume cs:codesgdata segmentdb '1975','1976','1977','1978','1979','1980','1981','1982','1983'db '1984','1985','1986','1987','1988','1989','1990','1991','1992'db '1993','1994','1995';以上是表示21年的21个字符串dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000;以上是表示21年公司总收入的21个dword型数据dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226dw 11542,14430,15257,17800;以上是表示21年公司雇员人数的21个word型数据data endstable segmentdb 21 dup('year summ ne ?? ')
table ends codesg segmentstart:mov ax,datamov ds,axmov ax,tablemov es,axsub bx,bxsub di,disub si,simov cx,21all: ;年份存入table段mov dx,ds:[di] ;年份的前2个字节mov es:[bx],dx mov dx,ds:[di+2] ;年份的后2个字节mov es:[bx+2],dx ;收入存入table段mov ax,ds:[di+84] ;收入的前2个字节 ;将收入的前两个字节放入axmov es:[bx+5],ax mov dx,ds:[di+84+2] ;收入的后两个字节 ;将收入的后两个字节放入dxmov es:[bx+7],dx;雇员数存入table段mov bp,ds:[si+168] ;雇员的全部字节mov es:[bx+10],bp;人均收入存入table段div bp ;计算平均收入mov es:[bx+13],axadd di,4add si,2add bx,16loop allmov ax,4c00Hint 21Hcodesg endsend start
运行结果:

本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
