课程设计一 :
;**********************************************************
;课程设计1,将下面的data中的数据 按照表格的形式显示在屏幕上
;**********************************************************
assume cs:code,ds:data
data segment
db 11 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'
;以上是表示21年的21个字符串
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型数据
dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
dw 11542,14430,45257,17800
;以上是表示21年公司雇员人数的21个word型数据
data ends
code segment
start:
mov ax,data
mov ds,ax
mov cx,21
sub si,si
mov bx,0
mov dh,2
s0:
push cx
mov di,dx ;此处一定要注意,实现的是si能加四,注意数据段中各种数据的类型!!
mov cl,02h
mov dl,0
;**************************************
;把年份送到table中
;**************************************
mov ax,[si+11]
mov ds:[0],ax
mov ax,[si+2+11]
mov ds:[2],ax
mov byte ptr ds:[4], 0
push si
mov si,0
call show_str
pop si
;********************************************
;把收入送到table中
;********************************************
mov ax,[si+84+11]
mov dx,[si+86+11]
push si
call dtoc
mov dx,di
mov dl,20
call show_str
pop si
;*************************************************************
;把人数送到table中,注意人数是双字节,所以每次不能增四,只能增二
;*************************************************************
sub si,bx
mov ax,[si+168+11]
mov bp,ax
sub dx,dx
add si,bx
push si
call dtoc
mov dx,di
mov dl,40
call show_str
pop si
;**************************************
;计算人均收入并把其送到table中
;*****************************************
mov ax,[si+84+11]
mov dx,[si+86+11]
div bp
sub dx,dx ;只要人均值,余数不要
push si
call dtoc
mov dx,di
mov dl,60
call show_str
pop si
add si,4
add bx,2
inc dh
pop cx
loop s0
mov ax,4c00h
int 21h
;********************************************************
;数字转化为字符串子程序
;*********************************************************
dtoc:
push ax
push cx
push dx
mov si,9
dnext:
mov cx,10
call divdw
add cx,30h
mov [si],cl ;将转换好的字符串放到我们定义的数据段中
dec si
cmp dx,0
jne dnext
cmp ax,0
jne dnext
inc si
pop dx
pop cx
pop ax
ret
;********************************************
;防溢出除法子程序
;*******************************************
divdw:
jmp short divstart
datareg dw 4 dup (0)
divstart:
push bx
push ds
push si
cmp dx,cx ;通过这里实现兼容没有溢出的除法
jb divnoflo
mov bx,cs
mov ds,bx
mov si,offset datareg
mov [si],ax ;保存低16位L
mov ax,dx ;求H/N,得到int(H/N)和rem(H/N),分别保存在ax和dx当中
sub dx,dx ;***这个语句非常重要,对dx清零,避免溢出
div cx
mov [si+2],dx ;保存rem(H/N)
mov bx,512 ;求得int(H/N)*65536
mul bx
mov bx,128
mul bx
mov [si+4],ax ;保存int(H/N)*65536
mov [si+6],dx
mov ax,[si+2] ;求得rem(H/N)*65536
mov bx,512
mul bx
mov bx,128
mul bx
add ax,[si] ;求得rem(H/N)*65536+L
div cx ;求得[rem(H/N)*65536+L]/N ***注意这里进行的除法不能清除dx,这里不可能会溢出
mov cx,dx ;求得结果得余数
add ax,[si+4] ;求得结果的低16位
mov dx,[si+6] ;求得结果得高16位
jmp short dsret
divnoflo:
div cx
mov cx,dx
sub dx,dx
dsret:
pop si
pop ds
pop bx
ret
;***********************************************************
;显示字符串子程序
;***********************************************************
show_str:
push ax ;注意子程序中要用到的寄存器要保存起来
push dx
push cx
push es
push di
push si
push bx
mov ax,0
mov al,0a0h
mul dh
mov bx,ax
mov al,2
mul dl
add bx,ax ;得到偏移地址=dh*160+dl*2
mov di,bx ;将偏移地址保存起来
mov ax,0B800H
mov es,ax
mov al,cl
mov cx,0
s:
mov cl,ds:[si]
jcxz next ;进行判断最后一个字符是否是零,如果是零则结束
mov es:[di],cl ;将字符串放到偶地址中
mov es:[di+1],al ;颜色属性放到奇地址中
add di,2
inc si
jmp short s
next:
pop bx
pop si
pop di
pop es
pop cx
pop dx
pop ax
ret
code ends
end start