|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
assume cs:code,ds:data
data segment
db 1000 dup (0)
db '1975','1976','1977','1978','1979','1980','1981','1982','1983'
db '1984','1985','1986','1987','1988','1989','1990','1991','1992'
db '1993','1994','1995'
dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
dw 11542,14430,15257,17800
data ends
code segment
start:
mov ax,data
mov ds,ax ;将data的偏移地址写入ds
mov bx,0
mov si,1000
mov di,0 ;初始化bx,si,di的值,data段首定义了1000个0,所以si的值等于1000
call year ;调用子程序:year(年)
mov bx,0
mov cx,0
mov bp,0
mov si,1084
mov di,0 ;初始化bx,cx,bp,si,di的值,21年年收入的第一个数据的偏移地址等于1084
(1000+84,1000是data段首写义的1000个0,84是21年*4=84个字节)
call income ;调用字程序,income(年收入)
mov bx,0
mov cx,0
mov bp,0
mov si,1168
mov di,0 ;初始化bx,cx,bp,di和si的值,第三组数据——公司员工数的第一个数据地址为ds:[si],si=1168d
call staff ;调用子程序staff(员工),该子程序的作用是将员工数显示出来
mov bp,0
mov bx,0
mov si,1084
mov di,1168 ;初始化,si用来指向公司年收入数据,再写入ax和dx作为被除数;di用来指向公司职工数,再写入cx作为除数
call renjun ;调用子程序renjun(人均),该程序的作用是算出人均收入,并转换成ASCII码值,写入显存
mov ax,4c00h
int 21h ;程序返回,打完收功!
xianshi: ;子程序:xianshi(显示)开始,该子程序的作用是计算行与列的偏移地址
mov ax,160 ;一行有160个字节,所以ax=160
dec dh
mul dh ;行数减1后和ax相乘,计算出行数的偏移地址
mov bx,ax ;再将行数的偏移地址写入bx
mov ax,2 ;一列有2个字节,所以ax=2
dec dl
mul dl ;列数减1后和ax相乘,计算出列数的偏移地址
add bx,ax ;再将列数的偏移地址和行数的偏移地址相加,存入bx
mov al,cl ;cl保存的是字符属性,将cl转存入al,因为后面的程序中要占用到cl
ret ;返回
year: ;字程序year(年)开始
push ax
push bx
push cx
push dx
push si
push di ;将ax,bx,cx,dx,si,di压栈
mov ax,0b800h
mov es,ax ;将偏移地址b800h写入es。b800h是显存的地址
mov dh,3
mov dl,24
mov cl,02 ;定义行数、列数、字符属性
call xianshi ;调用字程序,xianshi(显示)
mov cx,21 ;循环21次,有21年嘛。呵呵
s:mov di,0
push cx ;将cx压栈,后面嵌套循环还要用到cx
mov cx,4 ;嵌套循环开始,循环4次
s1:mov ah,[si] ;将(ds:[1000])处的值写入ah
mov es:[bx+di],ah ;将ah写入(es:[bx+di])处(将字符写入显存)
mov es:[bx+di+1],al ;将al写入(es:[bx+di+1])处(将字符属性写入显存)
inc si ;si自增1
add di,2 ;di自增2,一列有两个字节嘛
loop s1 ;返回s1
add bx,160 ;第一年四个字符都写入显存后,第二年的四个字符要换一行显示,所以bx要加160
pop cx
loop s ;返回到s处继续循环
pop di
pop si
pop dx
pop cx
pop bx
pop ax ;还原di,si,dx,cx,bx,ax的值
ret ;返回
income: ;字程序income(年收入)开始
push ax
push bx
push cx
push dx
push si
push di
push bp ;妈的,又要入栈啊,没办法。整吧!
mov cx,21 ;又要循环21回
s2:mov bp,0 ;初始化bp为0,作用是在子程序divw中记录将dx压栈的次数,再将bp写入cx作为循环次数
mov ax,[si] ;把(ds:[1084])处的值写入ax(32位中的低16位)
mov dx,[si+2] ;把(ds:[si+2])处的值写入dx(32位中的高16位)
call divw ;调用子程序:divw,该程序的作用是进行不会溢出的除法,从而算出每一位数的ASCII码值
add si,4 ;不用我说了吧!32位的!
loop s2 ;返回s2循环21回
mov dh,3
mov dl,33
mov cl,02 ;知道什么意思吧,不会吧?真的不知道??我靠!定义行数、列数和字符属性!
call xianshi ;调用子程序xianshi(显示)
mov si,0 ;初始化si和di的值,si=0,那么ds:[si]就直接指向data段首
mov di,0 ;这个用说了,地球人都知道。
mov cx,21 ;又来一个21回的循环,谁叫他妈的是21年呢。
s6:push cx
s5:mov cl,[si] ;将(ds:[si])处的值写入cl
mov ch,0
jcxz ok2 ;判断cx是否为0,若为0则跳到ok2处执行,若不为0则向下执行
mov es:[bx+di],cl
mov es:[bx+di+1],al ;将cl和al写入显存
inc si ;si自增1
add di,2 ;di加2,因为一列有两个字节
jmp short s5 ;跳到s5继续循环
ok2:add bx,160 ;上面的cx为0,则跳到此处,要换一行显行下一个数据,所以bx加160
inc si
mov di,0 ;di初始化为0,因为只是加了一行,列数不变
pop cx
loop s6 ;这个你懂的
pop bp
pop di
pop si
pop dx
pop cx
pop bx
pop ax ;郁闷的POP
ret ;嘿嘿
divw: ;子程序divw开始,进行不会溢出的除法,从而算出每一位数的ASCII码
push bx
push cx
push dx
push si ;“我不想说,我很纯洁”
s3:mov cx,10 ;除数为10,除以10才能算出一组数据每一位上的数值,再加30h就得出ASCII码值,再......
push ax
mov ax,dx
mov dx,0
div cx
mov bx,ax
pop ax
div cx
mov cx,ax ;进行不会溢出的除法,这个都不懂的话,去翻书,别问我
jcxz ok1
add dx,30h
push dx
inc bp ;核心部分,算出一组数据每一位数的ASCII码值,push保存,保存一次,bp自增1
mov dx,bx
jmp short s3 ;bx的值写入高16位dx,再跳到s3继续进行不会溢出的除法
ok1:add dx,30h
push dx
inc bp ;核心部分,算出一组数据每一位数的ASCII码值,push保存,保存一次,bp自增1
mov cx,bp ;把bp的值写入cx,准备进行循环
s4:pop ax
mov [di],al
inc di
loop s4 ;循环四回,将前面push进去的dx的ASCII码值依次写入ds:[di]
mov byte ptr [di],0 ;一组数据写入完成以后,写一个0进去,方便在以后在程序中jcxz命令能准确判断一组数据是否写完
inc di
pop si
pop dx
pop cx
pop bx ;忠实的pop
ret
staff: ;子程序staff(员工)开始
push ax
push bx
push cx
push dx
push si
push di
push bp ;没完没了的push
mov cx,21 ;又要循环21回
s9:push cx ;将cx入栈,以后还会用到cx
mov bp,0 ;初始化bp为0,作用是在子程序divw中记录将dx压栈的次数,再将bp写入cx作为循环次数
mov ax,[si] ;把(ds:[si])处的值写入ax,si的初始值是1168d,被除数最历害的一组是17800d,除以10d是不会溢出的,所以直接做除法运算就OK
s7:mov cx,10 ;定义除数为10
mov dx,0 ;dx一定要设为0,因为它默认是32位除法的高16位
div cx ;开始除了
mov cx,ax ;把商写入cx,方便jcxz命令判断其是否为0
jcxz ok3 ;判断cx是否为0,为0则跳到ok3执行
add dx,30h ;dx加30h,将其变成ASCII码
push dx
inc bp ;一样的,push dx一次,bp就自增1,作为后面循环的依据
jmp short s7 ;跳回s7继续
ok3:add dx,30h ;上面cx为0,则跳到此处,把最后一次余数(dx)加30h变成ASCII码
push dx
inc bp ;原理同上
mov cx,bp ;将bp的值写入cx准备循环
s8:pop ax
mov [di],al
inc di ;将之前压入栈的dx逐个出栈,再写入ds:[di]保存
loop s8
mov byte ptr [di],0 ;一组数据结束后,写入一个0,方便以后的程序中jcxz命令的判断
inc di
add si,2 ;不用我说了吧,16位的
pop cx ;还原cx的值,确保循环21次
loop s9 ;返回s8循环21回
mov dh,3
mov dl,43
mov cl,02 ;知道什么意思吧,不会吧?真的不知道??我靠!定义行数、列数和字符属性!
call xianshi ;调用子程序xianshi(显示)
mov si,0 ;初始化si和di的值,si=0,那么ds:[si]就直接指向data段首
mov di,0 ;这个用说了,地球人都知道。
mov cx,21 ;又来一个21回的循环,谁叫他妈的是21年呢。
s11:push cx
s10:mov cl,[si] ;将(ds:[si])处的值写入cl
mov ch,0
jcxz ok4 ;判断cx是否为0,若为0则跳到ok2处执行,若不为0则向下执行
mov es:[bx+di],cl
mov es:[bx+di+1],al ;将cl和al写入显存
inc si ;si自增1
add di,2 ;di加2,因为一列有两个字节
jmp short s10 ;跳到s10继续循环
ok4:add bx,160 ;上面的cx为0,则跳到此处,要换一行显行下一个数据,所以bx加160
inc si
mov di,0 ;di初始化为0,因为只是加了一行,列数不变
pop cx
loop s11 ;这个你懂的
pop bp
pop di
pop si
pop dx
pop cx
pop bx
pop ax ;郁闷的POP
ret ;嘿
renjun: ;子程序renjun(人均)开始
push ax
push bx
push cx
push dx
push si
push di
push bp ;发现打这些push速度已经很快了
mov cx,21 ;21年,不想再说了
s14:mov bp,0 ;bp记录入栈记数,一组数据结束,bp还原为0
push cx ;保存起来,后面还要用到cx
mov ax,[si]
mov dx,[si+2] ;定义被除数
mov cx,[di] ;定义除数
div cx ;不会溢出的,直接除算了,这次除是为了先算出人均年收入
s12:mov cx,10d ;定义除数,这一次是用来算出人均收入数据的ASCII码值的
mov dx,0 ;dx一定要设为0,它表示的是32位的高16位
div cx ;直接整,没事儿
mov cx,ax ;将ax写入cx,方便后面jcxz好判断
jcxz ok5 ;判断,如果cx为0,则跳到ok5
add dx,30h ;余数dx加上30h,就是人均收入数据每一位上的数的ASCII码值
push dx ;将dx入栈保存
inc bp ;每入一次栈,bp就自增1,作用是为了cx的循环提供依据
jmp short s12 ;跳回s12继续
ok5:add dx,30h
push dx
inc bp ;上面如果cx为0,则跳到此处,最后一位数加30h变成ASCII码......
mov cx,bp ;将bp的值写入cx,为循环提供依据
s13:pop ax ;将之前入栈的dx的ASCII码出栈到ax
mov [bx],al ;将al写入data段首
inc bx
loop s13
mov byte ptr [bx],0 ;写一个0进去,方便后面的jcxz命令判断
inc bx
pop cx ;还原cx的值
add si,4
add di,2 ;(ds:[si])指向的是32位的数据,故si+4;(ds:[di])指向的是16位的数据,故di+2
loop s14 ;返回到s14继续
mov dh,3
mov dl,53
mov cl,2 ;定义行、列、字数属性
call xianshi ;调用子程序xianshi(显示)
mov si,0
mov di,0 ;初始化si和di,使ds:[si]指向data段首,di指向显存的列
mov cx,21 ;21年
s16:push cx ;入栈保存
s15:mov cl,[si]
mov ch,0
jcxz ok6 ;将(ds[si])写入cl,ch为0,判断cx是否为0,为0则跳
mov es:[bx+di],cl
mov es:[bx+di+1],al ;写入显存
inc si
add di,2 ;si自增1,di加2(一列两个字节)
jmp short s15 ;跳到s15继续
ok6:add bx,160
inc si
mov di,0 ;一组数据写完,跳一行再写另一组数据,故bx加160;每一组数据,列数不变,故di=0
pop cx ;还原cx
loop s16 ;跳到s16继续
pop bp
pop di
pop si
pop dx
pop cx
pop bx
pop ax ;不想说了
ret
code ends
end start
|
|