;方案一: 根据实验7,先将数据按照规定格式存储,然后在显示的时候再将数据转化为字符串显示出来;
;方案二:根据实验7,先将数据按照一定的格式并转化为字符串进行存储,然后在显示的时候直接显示出来;
;以下用的是用的是方案一作为设计方案:
assume cs:code,ds:data
;源数据段
data segment
db '1975','1976','1977','1978','1979','1980','1981'
db '1982','1983','1984','1985','1986','1987','1988'
db '1989','1990','1991','1992','1993','1994','1995'
;以上是表示21年的21个字符串。共84个字节,起始单元:0
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型数据。共84个字节,起始单元:84
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型数据。共42个字节,起始单元:168
data ends
;经转化后的目标数据段
table segment
db 21 dup ('year summ ne ?? ')
table ends
;用于存储字符属性,并作为栈空间使用的段
rgb segment
db 00000010b;0、黑底绿字
db 01000010b;1、红底绿字
db 01110001b;2、白底蓝字
db 00100100b;3、绿底红字
db 11000010b;4、红底闪烁绿字
db 01001010b;5、红底高亮绿字
db 00000111b;6、黑底白字
db 48 dup (0) ;真正作用于栈段的内存空间
rgb ends
;用于存储显示到DOS的临时字符串的数据段
form segment
db 10 dup(20h)
form ends
code segment
start:
mov ax,rgb
mov ss,ax
mov sp,40h
call init ;初始化公司数据
mov bp,6 ;设置字体颜色编号
mov dh,2 ;设置初始行号(共25行,0~24)
mov di,0 ;table的行偏移
mov cx,21
Lp:
push cx ;当前循环
mov dl,19 ;设置初始列号(共80列,0~79)
mov si,0 ;0年份
add si,di
mov cx,0 ;设置除数为0,表示当前数据为字符串;否则为数字
call setForm
call show_str
mov si,5 ;5总收入?
add si,di
mov cx,1 ;设置除数为0,表示当前数据为字符串;否则为数字
mov bx,0 ;bx=0,表示被除数为dword型;否则表示被除数为word型
call setForm
call show_str
mov si,10 ;10雇员人数
add si,di
mov cx,1 ;设置除数为0,表示当前数据为字符串;否则为数字
mov bx,1 ;bx=0,表示被除数为dword型;否则表示被除数为word型
call setForm
call show_str
mov si,13 ;13人均收入
add si,di
mov cx,1 ;设置除数为0,表示当前数据为字符串;否则为数字
mov bx,1 ;bx=0,表示被除数为dword型;否则表示被除数为word型
call setForm
call show_str
inc dh ;下一行数据
add di,16
pop cx
loop Lp
mov ax,4c00h
int 21h
;将数据转化为字符串,并存储到临时数据段
setForm:
push dx ;保存DOS显示时的行和列
push di
mov ax,table
mov ds,ax
mov ax,form
mov es,ax
mov di,0
mov ax,[si] ;dword型数据的低16位
mov dx,2[si] ;dword型数据的高16位
jcxz year
mov cx,bx ;bx=0,表示被除数为dword型;否则表示被除数为word型
jcxz isDword
mov dx,0
isDword:
call dtoc
jmp short R_sf
;复制到格式数据段
year: mov es:[di],ax
mov es:2[di],dx
mov byte ptr es:4[di],0
R_sf:
pop di
pop dx
ret
;将数字转化为字符串
dtoc:
mov di,0 ;记录转化的字符个数
Jp_dtoc:
mov cx,10 ;设置除数为10
call divdw
add bl,30h
push bx ;保存余数
inc di
mov cx,dx ;判断高16位是否为0
jcxz Jz_ax
jmp short Jp_dtoc
Jz_ax: mov cx,ax ;判断低16位是否为0
jcxz Jz_dtOk
jmp short Jp_dtoc
Jz_dtOk:
mov cx,di
mov di,0
Lp_dt: pop es:[di] ;将已转化的数据重新排列到存储临时字符串的数据段
inc di
loop Lp_dt
mov byte ptr es:[di],0 ;设置结束标记
ret
;ax(dword型数据的低16位);dx(dword型数据的高16位);cx(除数);bx(余数)
divdw: mov bx,ax ;BX未计算的低16位
mov ax,dx
mov dx,0 ;由于忘记清0,所以结果老是不对
div cx
mov si,ax ;SI已计算的高16位
mov ax,bx
div cx ;AX即是商,也是已计算的低16位
mov bx,dx ;设置余数
mov dx,si ;设置高16位
ret
;初始化公司的信息数据,并按要求存储到Table段中
init:
;设置数据段和附加段
mov ax,data
mov ds,ax
mov ax,table
mov es,ax
mov bx,0 ;设置年份和总收入的偏移地址
mov si,0 ;设置雇员人数的偏移地址
mov di,0 ;设置目标数据段的偏移地址
mov cx,21 ;设置循环次数,共有21条数据
;从数据段中复制年份到目标数据段中
Lp_i: mov ax,[bx] ;年份的前两个字节
mov es:[di],ax
mov ax,2[bx] ;年份的后两个字节
mov es:2[di],ax
;从数据段中复制总收入到目标数据段中,不同数据项以空格隔开(di=4)
mov ax,84[bx] ;总收入的低16位
mov es:5[di],ax
mov dx,86[bx] ;总收入的高16位
mov es:7[di],dx
;计算人均收入=总收入(AX,DX)/雇员人数, 不考虑除法溢出的问题
div word ptr 168[si] ;商存入AX中,不考虑余数
mov dx,168[si]
mov es:10[di],dx ;复制雇员人数,不同数据项以空格隔开(di=9)
mov es:13[di],ax ;存入人均收入,不同数据项以空格隔开(di=15)
;指向一下条(年)的数据
add bx,4
add si,2
add di,16
loop Lp_i
ret
;将临时字符串显示到DOS界面中
show_str:
push di
push dx
;设置数据段和附加段(显示缓冲区)
mov ax,form
mov ds,ax
mov ax,0b800h
mov es,ax
mov al,0a0h
mul dh ;计算行数的实际地址
mov di,ax
mov al,2h
mul dl ;计算列数的实际偏移地址
add di,ax
mov ah,[bp] ;取色
mov bx,0
mov si,0
mov ch,0
Jp_ss: mov cl,[si]
jcxz R_ss
mov al,cl ;取字
mov es:[di][bx],ax ;显示字符.
inc si
add bx,2
jmp short Jp_ss
R_ss: pop dx
pop di
add dl,10
ret
code ends
end start