⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cal.asm

📁 汇编所写的日历程序源代码
💻 ASM
📖 第 1 页 / 共 2 页
字号:


radix 16                               ; gentlemen prefer hex


doscall macro                          ; call to dos int_21 with a
mov ah,#1                              ; one-byte function in ah
int 21
#em

doscall2 macro                         ; call to dos int_21 with a
mov ax,#1                              ; two-byte function in ax
int 21
#em

dosprint macro                         ; call to dos string-print function
mov dx,offset #1
mov ah,09
int 21
#em

zero macro                             ; zero a register
xor #1,#1
#em


;     assembly options :

;  un-comment the next line to make monday the first day of the week :
;  monday    equ  1

;  un-comment the next line to remove the asterisk marking today's date :
;  no_splat  equ  1

;  un-comment the next line to prevent expanding years 00-99 to 2000-2099 :
;  no_2dig   equ  1

;  un-comment the next line to prevent pausing year calendar after june :
;  no_pause  equ  1


;     uninitialized variables :

julian_lo    equ  005e                 ; total number of days since
julian_hi    equ  0060                 ; december 31, 1752   (two words)

cal1         equ  0064                 ; temp storage for year-calendar
                                       ; print routine   (three bytes)

today        equ  0067                 ; today's date (byte)

month        equ  0068                 ; 1 = january, 12 = december (word)

year         equ  006a                 ; 1800 through 2199 (word)


;     start of code :

begin:
doscall 2a                             ; get date from dos
#if !no_splat
mov b [today],dl                       ; remember today's date
#endif
mov w [year],cx                        ; use current year as default
mov dl,dh
mov dh,00                              ; convert month to a word value
mov w [month],dx                       ; and use it as default
call parse                             ; read the command line
mov ax,w [year]
cmp ax,01753xd                         ; any year less than 1753
jb val_yx                              ; is an error
cmp ax,02399xd                         ; any year above 2399
ja val_yx                              ; is an error
mov ax,w [month]
cmp ax,0001                            ; any month below 1
jb val_mx                              ; is an error
cmp ax,000c                            ; any month above 12
ja val_mx                              ; is an error
call print_cal                         ; display calendar
int 20                                 ; and exit

val_yx:                                ; bad year --
mov dx,offset msg_year_bad             ; point to bad-year error message
jmp short val_2                        ; and skip ahead
val_mx:                                ; bad month --
mov dx,offset msg_month_bad            ; point to bad-month error message
val_2:
doscall 09                             ; print error message
int 20                                 ; and exit

parse:                                 ; read the user's command line:
mov si,0081                            ; start of command line
call skip_junk                         ; skip over any leading spaces
call test_digit                        ; is next character a digit?
je parse_cal                           ; if so, get user's value(s)
cmp bl,0d                              ; end of line?  if so, exit
jbe ret                                ; otherwise fall through to ....

syntax:                                ; syntax error:
dosprint msg_syntax                    ; print an error message
int 20                                 ; and exit

parse_cal:                             ; get calendar month and year values:
#if !no_splat
mov b [today],00                       ; forget today's date
#endif
call get_num                           ; get first user value
jc ret                                 ; any error, exit (use defaults)
mov w [month],ax                       ; save first value as month
call skip_junk                         ; and skip over any separator chars
call get_num                           ; get second value
jnc > l4                               ; save second value as year and exit
                                       ; only one value on command line :
dec b [flags]                          ; note full-year calendar
mov ax,w [month]                       ; change month to 1 (january]
mov w [month],0001                     ; and move first value into the year
l4:
#if !no_2dig
cmp ax,0100xd
jae > l5
add ax,02000xd
l5:
#endif
mov w [year],ax
ret                                    ; and exit

is_junk:                               ; junk that needs to be skipped ....
inc si                                 ; ignore it and fall through

skip_junk:                             ; skip past any separator characters:
mov al,b [si]                          ; examine next char on command line
cmp al,20                              ; space?
je is_junk                             ; skip over spaces
cmp al,'/'                             ; slash?
je is_junk                             ; skip over slashes
cmp al,'-'                             ; minus?
je is_junk                             ; skip over minuses
                                       ; anything else should not be ignored
                                       ; so fall through to exit
get_num_bad:
stc
ret

get_num:                               ; parse number from command line:
zero ax                                ; start with a value of zero
mov cx,000a                            ; ten, used for multiplications
call test_digit                        ; is the first character a digit?
jne get_num_bad                        ; if not, return error
l1:                                    ; number-parsing loop:
call test_digit                        ; is next character a digit?
jne get_num_okay                       ; if not, done parsing number; exit
inc si                                 ; if so, accept digit
sub bl,'0'                             ; convert ascii to value 0 - 9
mov bh,00                              ; 2-byte value
mul cx                                 ; multiply working value by ten
cmp dl,ch                              ; overflow during multiplication?
jne get_num_bad                        ; if overflow, return error
add ax,bx                              ; add in value of digit
jnc l1                                 ; if no overflow, loop back for next
ret

test_digit:                            ; is next character a digit?
mov bl,b [si]                          ; get next character
cmp bl,'0'
jb ret                                 ; no, exit with .z flag clear
cmp bl,'9'
ja ret                                 ; no, exit with .z flag clear
get_num_okay:
cmp bl,bl                              ; yes, exit with .z set
ret

compute_julian:                        ; convert date to julian number:
mov ax,w [year]                        ; get year in .ax
mov bx,ax                              ; and in .bx
cmp ax,02000xd                         ; year 2000?
je > l0                                ; if so, definitely a leap year
mov cl,0100xd
div cl
cmp ah,00                              ; is year divisible by 100?
je > l1                                ; if so, not a leap year
test bl,03                             ; is year divisible by 4?
jne > l1                               ; if not, not a leap year
l0:                                    ; leap year!
mov b [months_table+1],1d              ; 29 days in february
l1:
zero cx                                ; .cx holds a convenient zero
mov bp,cx                              ; start with january
#if monday
mov w [julian_lo],cx
#else
mov w [julian_lo],0001
#endif
mov w [julian_hi],cx                   ; and a julian date of four
l2:
mov al,b [months_table+bp]             ; get length of month
cbw                                    ; as a two-byte value
inc bp
cmp bp,w [month]                       ; hit the user's month yet?
je > l4                                ; yes, exit this loop
add w [julian_lo],ax                   ; no, add month length into julian
jmp SHORT l2                                 ; and loop back for next month
l4:                                    ; added in lengths of previous months:
sub bx,01753xd                         ; normalize year to zero
mov ax,bx
mov dx,0365xd
mul dx                                 ; multiply year number by 365
add w [julian_lo],ax
adc w [julian_hi],dx                   ; and add into the julian date
mov ax,bx
shr ax,1
shr ax,1                               ; divide year number by four
add w [julian_lo],ax                   ; to get number of leap-days
adc w [julian_hi],cx                   ; add leap days into julian date
mov ax,bx
add ax,052xd
mov dl,0100xd
div dl                                 ; and divide by 100
cbw                                    ; to get number of non-leap xx00 years
sub w [julian_lo],ax
sbb w [julian_hi],cx                   ; subtract from julian date
cmp bx,0247xd
jbe > l8                               ; user year greater than 2000?
add w [julian_lo],0001                 ; if so, add one  (year 2000 is the
adc w [julian_hi],cx                   ; only leap century in program range)
l8:
mov dx,w [julian_hi]

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -