|
楼主 |
发表于 2012-10-1 10:26:44
|
显示全部楼层
课程设计1:
说明:在这里代码量虽然有点大,但是主体部分其实很少,其他的都是子程序。在这个课程设计中,本人主要是采用模块化开发,所谓模块化,其实就是多用子程序,将常用功能都做成子程序的形式。如果不用子程序这些,和优化结构,其实这个课程设计的总代码量也可以控制在 150行左右的。
另外,大家也可以利用在实验7中已经做过的TABLE表格,直接拿来用,那样也比较方便的。
assume cs:cseg,ds:dseg,ss:sseg
;常量定义
COLOR equ 2 ;显示文本的颜色:黑底绿色
HANG equ 1 ;文本显示位置:初始显示的行号(从0开始数)
LIE equ 2 ;文本显示位置:初始显示的列号(从0开始数)
;数据段设置
dseg segment
ty:
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型数据
tp:
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型数据
tsz:
db 12 dup (0)
;以上用于为显示数值字符串变量数组(那个显示字符串的子程序show_str要用到)
dseg ends
;堆栈段设置
sseg segment
db 100 dup (0)
sseg ends
cseg segment
start:
mov ax,sseg ;代码初始化工作
mov ss,ax
mov sp,100
mov ax,dseg
mov ds,ax
mov cx,21 ;21组数据,故循环21次
mov dh,HANG ;设置显示的初始位置
mov dl,LIE
mov bx,offset ty
mov si,offset tp
main_s:
push cx ;显示年份,先保存cx以方便重新赋值
push si
mov cx,4
mov si,offset tsz
ty_s:
mov al,[bx]
mov [si],al
inc si
inc bx
loop ty_s
mov si,offset tsz
mov cl,COLOR ;黑底绿字显示
call show_str
mov si,offset tsz ;变量数组清零
mov cx,12
call zerosz
add dl,6 ;年份和空格总占据6列
pop si
push si
push dx
mov ax,[bx+80] ;显示总收入,因前面已经有循环4次的inc bx,故此处只需+80
mov dx,[bx+82]
mov si,offset tsz
call dtoc
mov si,offset tsz
mov cl,2
pop dx
call show_str
mov si,offset tsz
mov cx,12
call zerosz
pop si
push si
add dl,9
push dx
mov ax,[si] ;显示雇员人数
sub dx,dx
mov si,offset tsz
call dtoc
mov si,offset tsz
mov cl,2
pop dx
call show_str
mov si,offset tsz
mov cx,12
call zerosz
pop si
add dl,7
push dx
mov ax,[bx+80] ;计算人均收入并显示
mov dx,[bx+82]
mov cx,[si]
add si,2
call divdw
push si
mov si,offset tsz
call dtoc
pop si
pop dx
push si
mov si,offset tsz
mov cl,2
call show_str
mov si,offset tsz
mov cx,12
call zerosz
pop si
pop cx
dec cx
jcxz main_end
inc dh
mov dl,LIE
jmp main_s
main_end:
mov ah,1 ;该代码作用为按任意键后再退出
int 21h
mov ax,4c00h
int 21h
;名称:show_str(子程序)
;功能:在指定的位置,用指定的颜色,显示一个用0结束的字符串。
;参数:(dh)=行号(取值范围0-24),(dl)=列号(取值范围0-79),
; (cl)=颜色,ds:si指向字符串的首地址。
;返回:es:di指向显示末位下一个。
show_str proc
push ax
push si
push dx
push cx
mov ax,160 ;一行有160字节
mul dh
mov di,ax
mov ax,2 ;一列占2个字节(含一个颜色字节)
mul dl
add di,ax
mov ax,0b800h
mov es,ax
mov al,cl ;用al保存颜色值
sub cx,cx
s_show:
mov cl,[si]
jcxz show_end
inc si
mov es:[di],cl
inc di
mov es:[di],al
inc di
jmp s_show
show_end:
pop cx
pop dx
pop si
pop ax
ret
show_str endp
;子程序:dtoc
;功能:将dword型数转变为表示十进制数的字符串,字符串以0为结束符。
;参数:(ax)=dword型数据的低16位
; (dx)=dword型数据的高16位
; ds:si指向字符串的首地址
;返回:无
;说明:本子程序需与解决除法溢出的子程序divdw一起使用方可行
dtoc proc
push ax
push cx
push dx
push si
push di
sub di,di ;位数计数器初始为0
dtoc_go:
mov cx,dx
jcxz cha_next
jmp go_on ;不为0则继续除以10
cha_next:
mov cx,ax
jcxz dtoc_over ;以上几行为验证数值是否计算完毕
go_on:
mov cx,10
call divdw
add cl,30h
push cx ;保存余数(顺序为从末位到首位)
inc di ;位数计数
jmp dtoc_go
dtoc_over:
mov cx,di
dtoc_s:
pop ax
mov [si],al
inc si
loop dtoc_s
pop di
pop si
pop dx
pop cx
pop ax
ret
dtoc endp
;子程序:divdw
;功能:进行不会产生溢出的除法运算,被除数为dword型,除数为word型,结果为dword型。
;参数:(ax)=dword型数据的低16位
; (dx)=dword型数据的高16位
; (cx)=除数
;返回:(dx)=结果的高16位,(ax)=结果的低16位
; (cx)=余数
divdw proc
push bx ;保护现场
push ax ;除法运算段
mov ax,dx
sub dx,dx
div cx
mov bx,ax
pop ax
div cx
mov cx,dx
mov dx,bx ;除法运算结束,配置返回值
pop bx ;恢复现场
ret
divdw endp
;子程序:zerosz数组内容清零
;参数:ds:si指向数组,cx为清零个数
;返回:无
zerosz proc
zerosz_s:
mov BYTE ptr [si],0
inc si
loop zerosz_s
ret
zerosz endp
cseg ends
end start
|
|