弄了两天多才搞定,累死我了。。。。。
assume cs:codesg,ds:data,es:table
data segment
db '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个字符串 0~53H
dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
;以上是表示21年公司总收入的21个dword型数据 54H~0A7H
dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
dw 11542,14430,15257,17800
;以上是表示21年公司雇员人数的21个word型数据 0A8H~0D1H
data ends
table segment
db 21 dup ('year sumn ne ?? ')
table ends
codesg segment
start:mov ax,data
mov ds,ax
mov ax,table ;表
mov es,ax
xor bx,bx
xor si,si
xor di,di
mov cx,21
call s
mov dh,8
mov dl,3
mov cl,2
call year_s
mov ax,4c00H
int 21H
s:mov ax,ds:[bx]
mov es:[si],ax ;19
mov ax,ds:[bx].2 ;75
mov es:[si].2,ax
mov ax,ds:[di].0A8H
mov es:[si].0AH,ax
mov ax,ds:[bx].54H
mov es:[si].5H,ax
mov dx,ds:[bx].56H
mov es:[si].7H,dx
div word ptr es:[si].0AH
mov es:[si].0DH,ax
add bx,4 ;因为年份和总收入都为4字节,人数为2字节
add di,2
add si,10H
loop s
ret
;==============================================|
;----------------年份子程序--------------------|
;==============================================|
year_s:push cx ;年份子程序
mov bx,0
mov si,0
c2:mov ax,0B800H ;显存地址
mov ds,ax
mov al,0a0h
mul dh ;8*160 要写入的偏移地址
mov bx,ax ;(bx)=(ax)
mov al,2
mul dl ;起始地址
add bx,ax ;(bx)=(bx)+(ax)
pop dx ;将cx中的值弹出栈放置dx里
mov cx,4 ;外层循环数
k:push cx
push bx
push si ;入栈是因为后面要用到这些
mov cx,21 ;内层循环数
k2:mov al,es:[si] ;es段为表段,此时si为0,取出其中字符
mov ah,dl ;原始cl里存放的是颜色属性信息,现在放入ah
mov ds:[bx],ax ;将ax中值放入ds:[内存单元]
add si,10H ;指向下一行,此时指向的字符是与开始si所对应位置的字符了 检索位置
add bx,0A0H ;bx为显存地址区偏移,(bx)=(bx)+0A0H,即字符输出的位置指向下一行与开始bx所对应位置的字符 输出位置
loop k2
pop si ;先前将si push进栈是为了混乱,现在pop 出来自加1 ,即指向要检索的下一个字符
inc si
pop bx ;将bx pop出栈加2,因为一个字节存放字符,一个存放属性
add bx,2
pop cx ;将cx的值还给它
loop k ;跳至外层循环检索下一字符
add bx,20
push bx ;bx记录了写入年份的偏移,现在保存起来,用作总收入写入的起始偏移地址
;==============================================|
;----------------总收入子程序------------------|
;==============================================|
icome:mov bx,0
pop si ;将年份的偏移地址pop出栈到si中,用作总收入写入的起始偏移地址
mov cx,21 ;循环次数
mov bp,0 ;bp定位es段中要查询的首地址,bp用作索引es段中的数据位置
mov di,si ;将要写入的起始偏移地址放到di中,di用作屏幕写入位置定位
push di
icome2:push cx ;将循环次数入栈保存,以免后继操作将cx打乱
mov ax,es:[bp+5] ;ax为低16位,es:[bp+5],指向了es段中第5个字节
mov dx,es:[bp+7] ;dx为高16位,es:[bp+7],指向了es段中第7个字节
call dwtoc ;跳转到dtoc,dtoc功能是将dword数据转换为十进制输出
add bp,10H ;初始bp为0,表明从0索引,现在bp加上10H(16),因为es段的长度为16个字节,现在加上16,表示将索引下一行与上一行对应的字符处,即索引第二行了
pop cx ;将循环次数pop出栈到cx中
loop icome2
;==============================================|
;------------------人数子程序------------------|
;==============================================|
number:pop si
add si,30
mov cx,21
mov bp,0
mov di,si
push di
number1:push cx
mov ax,es:[bp+0AH]
call dtoc
add bp,10H
pop cx
loop number1
;==============================================|
;---------------平均工资子程序-----------------|
;==============================================|
wage:pop si
add si,30
mov cx,21
mov bp,0
mov di,si
wage1:push cx
mov ax,es:[bp+0DH]
call dtoc
add bp,10H
pop cx
loop wage1
ret
dwtoc:mov cx,0 ;
push cx
dwtoc1:mov cx,10 ;cx为除数
call divdw ;跳转到divdw中,做不会溢出的除法运算
add cx,30H ;cx存放的是最后一次运算所得的余数,现在加30H,是为了得到它的ASCII码
push cx ;保存余数的ASCII码进栈
mov cx,dx ;判断商是否为0,如果高低位高都为0,则返回,首先判断高16位
jcxz dwtoc2 ;如果为0,则跳转到dtoc2,进行低位判断
jmp short dwtoc1 ;如果不为0,则跳转,继续进行除法运算
dwtoc2:mov cx,ax ;当高位为0时,判断低位
jcxz dwtoc3 ;如果低位也为0,表明除法运算已完成,已经获取了所有的余数的ASCII码,就跳转到dtoc3处,进行写入操作
jmp short dwtoc1 ;如果不为0,则跳转,继续进行除法运算
dwtoc3:pop cx ;因为先前将cx入栈了,cx中保存的是余数的ASCII码,现在出栈
mov ds:[si],cl ;cl保存的是余数,十进制
mov byte ptr ds:[si+1],2 ;mov byte ptr ds:[si+1],2 这句是给转换后字符赋颜色属性
jcxz dwtoc4 ;如果cx为0,则跳转到dtoc4处
add si,2 ;si+2是为下一个字符写入做准备
jmp short dwtoc3 ;如果cx不为0,则跳转到dtoc3处,继续写入字符
dwtoc4: mov byte ptr ds:[si],0 ;最后,当所有字符写入完毕后在末尾加0
; pop cx
; mov si,0
add di,0A0H ;先前di中存放的是将要写入的起始偏移地址,现在加上0A0H,表明是指向屏幕的下一行,也就是指向了与上一行所对应的字符处
mov si,di ;di中已经存放了要写入的下一行的地址,现在将di中的值放到si中,因为si将会用作下一次循环,用作写入地址
ret
divdw:mov bx,ax ;将ax的值临时存放到bx中
mov ax,dx ;此时ax为高16位
xor dx,dx
div cx ;ax为商,dx为余数 rem(H/N)*1000H+L
push ax ;高16位运算结果所得的商入栈
mov ax,bx ;此时ax为低16位
div cx ;结果:ax存放低16位,dx存放高16位,cx存放余数
mov cx,dx ;dx存放的是余数,现在将它给cx
pop dx ;第一次是进行高16位运算,现在将它还给dx,dx中存放的是高16位商
ret
dtoc:mov cx,0 ;cx为0入栈是为了下面的操作
push cx
dtoc1:mov cx,10
xor dx,dx
div cx ;L/N ax为商,dx为余
mov cx,dx ;把余放入cx中
add cx,30H ;现在cx+30为余数的ASCII码
push cx ;保存余数的ASCII码进栈
mov cx,ax ;将ax中的值放入cx中,判断ax的商
jcxz dtoc2 ;如果ax的商为零,表示各位余数都已经得到了,跳转至dtoc2处
jmp short dtoc1 ;如果商不为零,则跳转到dtoc1处继续进行除法运算,直到商为0止
dtoc2:pop cx
mov ds:[si],cl
mov byte ptr ds:[si+1],2
jcxz dtoc3
add si,2
jmp short dtoc2
dtoc3:mov byte ptr ds:[si],0
add di,0A0H
mov si,di
ret
codesg ends
end start
课程设计1
最新推荐文章于 2023-02-15 20:19:08 发布