设计题目:
用汇编语言编写一个打印月历的程序,要求用户在开始输入年、月。以后可以通过按下上下键来改变年份;左右键来改变月份。且每月的星期六、日用红色显示出来。
程序思路:
程序分为两大模块:主程序和具体打印部分。主程序负责处理用户的年、月输入;监测键盘动作,并把得到的信息处理成相应的入口参数送给打印模块。打印模块接受主程序的调用,对给定的年、月,打印出相应的月历。并且,处理界面上的要求。
程序中用到的算法(计算某一天是星期几):
蔡勒公式: W = [C/4] - 2C + y + [y/4] + [13 * (M+1) / 5] + d - 1
C是世纪数减一,y是年份后两位,M是月份,d是日数。1月和2月要按上一年的13月和14月来算,这时C和y均按上一年取值。
C是世纪数减一,y是年份后两位,M是月份,d是日数。1月和2月要按上一年的13月和14月来算,这时C和y均按上一年取值。
计算出来的结果模取7。
具体设计处理:
程序中多处使用了子程序,在主程序接受用户的年、月输入时,用GetYearMonth,此子程序把得到的合法输入放到数据段中的year和month变量中。所谓的合法变量是指输入的是数字字符(不是字母或者其他的字符)。否则,程序提示用户输入错误,接受用户的再次输入,直到用户输入的信息合法或者按下ESC键为止。
在每次得到合法的年、月后,就调用打印模块的display函数,程序以后就一直在这里循环,每次调用BIOS的16h号中断的0号功能,读取键盘的一个按键,并根据题目要求对上下左右键做出相应的动作。直到用户按下ESC为止。
在打印模块的display中,首先要把display设为public属性,以示此过程要被别的模块调用。display的入口参数是BX(year),DL,(month),进入display后首先做一下现场的保护,然后把DS的值切换到打印模块里来。接着把BX,DL里的值放到内存变量中,以腾出BX,DL来使用。下面开始设置程序运行的界面:每次都从DOS窗口的(0,0)处开始显示,所以把光标每次开始都设置在(0,0)处。在设置整个屏幕上的显示属性,使用10h号中断的6号功能。BH的性质如下:
bit0~2 :
字体颜色 (0:黑,1:蓝,2:绿,3:青,4:红,5:紫,6:综,7:白)
bit3 :
字体亮度 (0:字体正常,1:字体高亮度)
bit4~6 :
背景颜色 (0:黑,1:蓝,2:绿,3:青,4:红,5:紫,6:综,7:白)
bit7 :
字体闪烁 (0:不闪烁,1:字体闪烁)
接下来设置星期六、日两列的字体为红色。也是使用10h中断的6号功能。
然后打印出当前显示的是哪一年的哪一月,调用dispYM,即打印两个十进制数。
然后就可以打印出MON,TUR等字样,以标注哪天是星期几。
然后,计算出当前月的天数,调用GetMonthSize,把得到的结果放到数据段的MonthSize中。如果是1、2月,要根据
蔡勒公式进行变换。然后是计算当前月份的第一天是星期几的过程。计算出之后在屏幕上留下相应的空格(为了对齐!)。
剩下的就是根据Monthsize的大小进行循环的输出日期了,调用dispWeek,在此过程立,要注意一位数与两位数对格式的影响。另外,打印到星期天要输出换行。
具体程序代码
:
#
主模块:
;
月历打印
;
主程序设置好入口参数,
BX=
年份,
DL=
月份
;
调用子程序
display
;By wangrui
;2006-12-8
extrn display:far
Esccode equ 01h
Up equ 048h
Down equ 050h
Left equ 04bh
Right equ 04dh
dseg segment
Year dw 0
Month db 0
temp db 10 dup(0)
count dw ?
ErrMsg db 0dh,0ah,"The input NOT decimal! $"
dseg ends
cseg segment
assume cs:cseg,ds:dseg
start:
mov ax,dseg
mov ds,ax
call GetYearMonth
Ws:
mov bx,Year
mov dl,Month
call far ptr display
again:
mov ah,0
int 16h
cmp ah,Esccode
je Exit
cmp ah,Up
je NextY
cmp ah,Down
je PreY
cmp ah,Left
je PreM
cmp ah,Right
je NextM
jmp again
NextY:
inc Year
jmp Ws
PreY:
dec Year
jmp Ws
NextM:
inc Month
cmp Month,12
jbe skip0
mov Month,1
inc Year
skip0:
jmp Ws
PreM:
dec Month
cmp Month,1
jae skip1
mov Month,12
dec Year
skip1:
jmp Ws
Exit:
mov ah,4ch
int 21h
;**************************************************
GetYearMonth proc near
push ax
push cx