📄 cal.asm
字号:
mov ax,w [julian_lo]
mov cl,07
div cx ; divide julian date by seven
mov al,01 ; to get day of the week.
sub al,dl
ret ; and return offset in .al
print_cal: ; print a calendar:
call crlf ; blank line
inc b [flags] ; full-year calendar?
je print_year_cal ; if so, go do that
call header_out ; display month and year
call crlf ; end of line
dosprint msg_cal1 ; print days-of-week line
call crlf ; end of line
mov si,0006 ; print six rows of dates :
call compute_julian ; calculate offset for start of month
mov ch,al
l4:
call print_cal_line ; print a row of dates
call crlf ; and terminate print line
add ch,07 ; add seven to date offset
dec si ; done six rows yet?
jne l4 ; if not, loop back
ret ; if so, exit
print_year_cal: ; print full-year calendar:
zero si ; start in the first column
l0:
call header_out ; display month and year
mov cx,0009
call spaces_out
call compute_julian ; compute values for first of month
mov b [cal1+si],al ; save in temp variable
inc w [month] ; move on to next month
inc si ; and next column
cmp si,0003 ; printed three month names yet?
jne l0 ; no, loop back for more
call crlf ; yes, end print line
l2:
dosprint msg_cal1 ; print days-of-week line
dec si ; three times
jne l2
call crlf ; then end print line
sub w [month],0003 ; back to first-column month
mov si,0006 ; print six rows of dates
l5:
zero di ; start in first column
l6:
mov ch,b [cal1+di] ; get offset for start of month
call print_cal_line ; print a row of dates
add b [cal1+di],07 ; then add seven to date offset
inc w [month] ; move on to the next month
inc di ; in the next column
cmp di,0003 ; done three columns yet?
jb l6 ; no, loop back and do next column
call crlf ; terminate print line
sub w [month],0003 ; back to first-column month
dec si ; printed six rows yet
jne l5 ; no, loop back for more
call crlf ; print a blank line
add w [month],03 ; move ahead to next row of months
#if !no_pause
cmp w [month],0007 ; does july come next?
jne > l7 ; if not, no need to pause
mov bx,0001 ; handle for stdout --
doscall2 4400 ; ioctl get device data
and dl,82 ; examine device and stdout bits
cmp dl,82 ; standard output to the console?
jne > l7 ; if not, do not pause
dosprint msg_more ; time to pause: print pause message
l65:
mov ah,01 ; keyboard: check key buffer status
int 16
pushf ; save status
mov ah,00 ; keyboard: get key
int 16
popf ; are we flushing the key buffer?
jne l65 ; if so, loop back for more
l7:
#endif
cmp w [month],000c ; all done yet?
ja ret ; yes, exit
jmp print_year_cal ; no, loop back for next three months
print_cal_line: ; print row of dates:
mov cl,00 ; start in first day-of-week column
l2:
mov al,ch ; get date offset from .ch
add al,cl ; and add the column number
call out2dig ; print number if valid
inc cl ; next day-of-week column
cmp cl,07 ; done seven yet?
jne l2 ; nope, keep going
call space_out
int 21 ; yes, print two more trailing spaces
ret ; and exit
out2dig: ; print date in .al, if it is valid:
cmp al,00 ; zero?
je > l1 ; if so, not valid; print spaces
mov bx,w [month] ; get offset into month-lengths table
cmp al,b [months_table-1+bx] ; date value too large?
jbe > l2 ; no, print it
l1: ; invalid date value:
mov dx,offset msg_3sp ; print three spaces
l15:
doscall 09
ret ; and exit
l2: ; valid date value:
#if !no_splat
cmp al,b [today] ; is this today's date ?
jne > l3 ; if not, continue
mov dx,offset msg_today ; if so, print an asterisk and exit
jmp l15
#endif
l3:
cmp al,0a ; ten or greater? i.e., two digits?
jae > l4 ; yes, print two digits
push ax ; otherwise, save value
call space_out ; print a space
pop dx
add dl,'0' ; convert one-digit value to ascii
int 21 ; and print it
jmp short space_out ; print trailing space and exit
l4: ; print two-digit value:
call bcdout ; then print a space and exit
space_out: ; print a space:
mov dl,20 ; ascii value of a space
doscall 02 ; print it
ret
header_out: ; display month and year :
call six_spaces ; print six spaces
mov ax,w [month] ; get month number
mov cl,03
mul cl ; and multiply by three
mov bx,ax ; to get pointer to month name
mov ah,02 ; dos print-a-character function
l0: ; print three characters
mov dl,b [month_names-3+bx] ; get byte from month name
int 21 ; and print it
inc bx ; advance pointer
loop l0 ; and continue until done
call space_out ; print one space
mov ax,w [year] ; get the current year
mov cl,0100xd
div cl ; divide year by 100
mov bl,ah ; save the remainder
call bcdout ; print the century
mov al,bl ; get the remainder and fall through -
bcdout: ; print value in .al
aam ; unpack decimal digits
add ax,'0' by '0' ; and convert to ascii digits
push ax ; save the remainder
mov dl,ah
doscall 02 ; print the tens digit
pop dx ; get the ones digit
int 21 ; print the ones digit
ret
crlf: ; terminate print line:
dosprint msg_crlf ; print carriage return and line feed
ret
six_spaces: ; print six spaces :
mov cx,0006 ; load .cx with six and fall through
spaces_out: ; print .cx number of spaces:
mov ah,02 ; dos print-a-character function
mov dl,20 ; ascii value of a space
l0:
int 21 ; print it
loop l0 ; however many times
ret
flags: ; nonzero means full-year calendar
db 00
months_table: ; number of days in each month
db 1f, 1c, 1f, 1e, 1f, 1e, 1f, 1f, 1e, 1f, 1e, 1f
month_names: ; three-letter month names
db 'JanFebMarAprMayJunJulAugSepOctNovDec'
msg_syntax:
db 0d,0a
db 'CAL 1.07 Freeware',0d,0a
db 'Copyright 1998, Charles Dye',0d,0a
db 0a
db 'CAL',0d,0a
db 'CAL mm/yyyy',0d,0a
db 'CAL yyyy'
msg_crlf:
db 0d,0a,'$'
msg_year_bad:
db 0d,0a,'Year is 1753-2399!',0d,0a,'$'
msg_month_bad:
db 0d,0a,'Month is 1-12!',0d,0a,'$'
msg_cal1:
#if monday
db 'Mo Tu We Th Fr Sa Su'
#else
db 'Su Mo Tu We Th Fr Sa'
#endif
msg_3sp:
db ' $'
#if !no_pause
msg_more:
db 'More',0d,'$'
#endif
#if !no_splat
msg_today:
db ' * $'
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -