|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 雪球丶 于 2020-3-17 23:56 编辑
- assume cs:code,ss:stack
- data segment
- ;data
- 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年的字符串
-
- ;data + 54H (84)
- dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
- dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
- ;21个年份公司的总收入
-
- ;data + A8H(168)
- dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
- dw 11542,14430,15257,17800
- ;21个年份的雇员数
- data ends
- table segment
- ; 年份 收入 雇员 人均收入
- db 21 dup ('year summ ne ?? ')
- table ends
- ;创建一个数据段,用来存放格式化之后的数据,用空格填充
- ;每行 年份起始索引0,收入起始索引20,雇员数起始索引40,人均收入起始索引60
- format segment
- db 1680 dup (' ')
- db 0
- format ends
- stack segment
- db 128 dup(0)
- stack ends
- ;将12666以十进制的形式在屏幕的8行3列用绿色显示出来
- code segment
- start:
- mov ax,stack
- mov ss,ax
- mov sp,128
-
- mov ax,data
- mov ds,ax ;初始化数据段
- mov ax,table
- mov es,ax ;es指向table段地址
-
- ;es指向table段地址
- call dneat ;整理数据
-
-
- ;将数据中的数字转换为ascii
- mov ax,table
- mov es,ax ;table段
- mov ax,format
- mov ds,ax ;format段
- mov bx,0 ;table行索引
- mov si,0 ;format行索引
-
- mov cx,21
- ts:
- ;拷贝年份数据-字符串(四字节)
- mov ax,es:[bx]
- mov ds:[si],ax
- mov ax,es:[bx+2h]
- mov ds:[si+2h],ax
-
- ;将收入转换为ascii的数字(四字节)
- mov ax,es:[bx+5h] ;收入低16位
- mov dx,es:[bx+7h] ;收入高16位
- push bx
- push cx
- push si
- add si,20 ;写到format段每行的第20列处
- ;函数 dtoc
- ;将word(16位)型数据转变位标识十进制数的字符串,字符串以0结尾,存放在ds处
- ;输入参数:
- ; (ax) = 32位数字的第16位
- ; (dx) = 32位数字的高16位
- ; ds:si指向字符串首地址
- ;返回值: 无
- call dtoc
- ;最后一位多多加了一个0,把0去掉,改为空格
- mov al,20H
- mov ds:[di],al
- pop si
- pop cx
- pop bx
-
-
- ;将雇员数改为ascii的数字(2字节)
- mov ax,es:[bx+0ah]
- mov dx,0000h
- push bx
- push cx
- push si
- add si,40 ;写到format段每行的第40列处
- call dtoc
- ;最后一位多多加了一个0,把0去掉,改为空格
- mov al,20H
- mov ds:[di],al
- pop si
- pop cx
- pop bx
-
- ;将平均工资改为ascii的数字(2字节)
- mov ax,es:[bx+0dh]
- mov dx,0000h
- push bx
- push cx
- push si
- add si,60 ;写到format段每行的第60列处
- call dtoc
- ;最后一位多多加了一个0,把0去掉,改为空格
- mov al,20H
- mov ds:[di],al
- pop si
- pop cx
- pop bx
-
- add si,80
- add bx,16
- loop ts
- ;将format段的第22行第一个数据(21x80 + 1= 1681)改为0,作为输出结束标识
- mov ax,0
- mov ds:[1681],ax
-
- ;显示
- mov dh,1 ;第1行
- mov dl,0 ;第0列
- mov cl,2 ;颜色
- mov ax,format
- mov ds,ax
- mov si,0
- call show_str
-
- mov ax,4C00H
- int 21H
- ;将word(16位)型数据转变位标识十进制数的字符串,字符串以0结尾,存放在ds处
- ;输入参数:
- ; (ax)=word型数据
- ; ds:si指向字符串首地址
- ;返回值: 无
- ;32位除法所需的寄存器:DX被除数的高16位,AX被除数的低16位,reg,除数(这里是cx)结果:AX商,DX余数
- dtoc: ;mov dx,0000H
- mov di,si
- mov bx,0 ;字符长度计数
- ;输入参数:
- ; (ax)=dword型数据的低16位
- ; (dx)=dowrd型数据的高16位
- ; (cx)=除数
- ;返回值:
- ; (dx)=结果的高16位,(ax)=结果的低16位
- ; (cx)=余数
- s0: mov cx,0AH
- push bx ;divdw函数内部会改变bx的值,把bx暂存起来
- push si
- call divdw
- pop si
- pop bx
- push cx ;数据入栈,因为算出来的顺序是反的,所以用栈来倒一下
- inc bx
- ;检查商是否为0,为0则计算结束,跳出循环
- push ax ;ax寄存器的值后面还有用,先保存起来
- or ax,dx
- mov cx,ax
- pop ax
- jcxz s1
- inc di
- mov cx,2
- loop s0
- s1:
- mov di,si
- mov cx,bx
- ens:
- pop ax
- add ax,30H ;转换为ASCII
- mov ds:[di],al
- inc di
- loop ens
- mov cl,0 ;末尾写入0
- mov ds:[di],cl
- ret
-
- show_str:
- mov ax,0b800H ;显存地址
- mov es,ax
- ;计算像素点索引 = rowx160 + colx2
- add dl,dl
- mov al,dh
- mov bl,160
- mul bl ;计算出来的行号存储在ax中
-
- mov dh,0
- add ax,dx
- mov di,ax ;像素写索引
- mov dh,cl ;先用dl记录下颜色值,后面直接用dx寄存器写显存;CX寄存器在循环中会被用到,释放cl
- ws: ;写显存
- mov dl,ds:[si]
- mov es:[di],dx
- inc si
- add di,2
- ;查看下一位是否为0
- mov cx,0
- mov cl,ds:[si]
- jcxz wd ;若下一位为0,则跳转到wd处
- mov cx,2 ;给CX赋值,如果程序走到这里说明下一位不为0就让其不断循环继续往下写
- loop ws
- wd: ret
- divdw:
- mov si,ax ;低16位暂存在si中
- ;计算高16位,将16位计算转化为32位计算
- mov ax,dx
- mov dx,0
- div cx
- mov bx,ax ;H/N存放在BX中
- ;计算低16位
- mov ax,si
- div cx
-
- mov cx,dx
- mov dx,bx
- ret
-
-
- dneat:
- mov bx,0 ;bx作为data段四字节数据的索引 (每次增加4)
- mov si,0 ;si作为data段2字节数据的索引 (每次增加2)
- mov bp,0 ;bp作为table段的索引 (table每次增加16)
- mov cx,21
- dn_s:
- ;拷贝
- ;table中每年的数据相隔F个字节
- ;table中同一年数据头索引 year(0)-summ(5)-ne(A)-??(D)
- ; 长度(byte) 4 4 2 2
- mov ax,ds:[bx] ;拷贝年份字符串 4 byte 每次2byte
- mov es:[bp],ax
- mov ax,ds:[bx+2H]
- mov es:[bp+2H],ax
-
- mov ax,ds:[bx+54H] ;拷贝收入字符串 dd=4byte 每次2byte
- mov es:[bp+5H],ax
- mov ax,ds:[bx+56H]
- mov es:[bp+5H+2H],ax
-
- mov ax,ds:[si+0A8H]
- mov es:[bp+0AH],ax ;拷贝雇员字符串 dw=2byte
-
- ;除法计算会改变bx的值,先将bx入栈
- push bx
- ;计算平均收入
- ;load收入(4字节)
- mov ax,ds:[bx+54H]
- mov dx,ds:[bx+56H]
- ;load人数(2字节)
- mov bx,ds:[si+0A8H]
- div bx
-
- ;bx出栈
- pop bx
- ;保存计算结果(取整)(2字节)
- mov es:[bp+0DH],AX
-
- add bx,4H
- add si,2H
- add bp,10H
- loop dn_s
- ret
-
- code ends
- end start
复制代码
DOS的汇编debug真的太不友好了,调试了三个多小时.....还发现前面几个测试点的程序里面的bug |
-
|