Category : Assembly Language Source Code
Archive   : EASTER.ZIP
Filename : EASTER.ASM

 
Output of file : EASTER.ASM contained in archive : EASTER.ZIP

;EASTER.ASM -- program to print out the date Easter falls on for a
; given year
;
;Written by Scott R. Houck 12 Sept 88
;
;Usage: EASTER
;
;For example: EASTER 1988 (must be 4 digits)

CODE SEGMENT
ASSUME cs:CODE, ds:CODE
ORG 100h

start: jmp main

CR equ 0Dh
LF equ 0Ah

A dw ?
B dw ?
C dw ?
D dw ?
E dw ?
H dw ?
M dw ?

March db 'March ',0
April db 'April ',0

usage db 'Usage: EASTER ',CR,LF,0
errmsg db 'Invalid year',CR,LF,0

div_by macro number
xor dx,dx
mov bx,number
div bx
endm

;---------------------------------------------------------------------

main PROC NEAR

mov di,80h ;PSP parameter byte count pointer
mov cl,[di] ;move byte count to CL
xor ch,ch
jcxz no_params
jmp short scan

no_params: lea si,usage
call dstring
jmp exit

invalid: lea si,errmsg
call dstring
jmp exit

scan: inc di
mov al,' '
cld
repe scasb ;scan for first non-space char
dec di
inc cx
jcxz no_params
cmp cx,4 ;must be a 4-digit year
jne invalid
mov si,di
mov dl,10 ;used in multiplication below
xor bx,bx

convert: lodsb ;move digit to AL
sub al,'0'
jl invalid ;was the digit less than '0' ?
cmp al,9
jg invalid ;was the digit greater than '9' ?
cbw ;convert to word
push ax ;save digit
mov al,bl
mul dl ;AX = AL * 10
mov bx,ax ;result in BX
pop ax ;restore digit
add bx,ax ;add in digit
loop convert

push bx ;save the year

mov ax,bx ;A = year % 19
div_by 19
mov A,dx

pop ax ;B = year / 100
div_by 100 ;C = year % 100
mov B,ax
mov C,dx

div_by 4 ;D = B / 4
mov D,ax ;E = B % 4
mov E,dx

mov ax,B ;F = (B + 8) / 25
add ax,8
div_by 25

neg ax ;G = (1 - F + B) / 3
inc ax
add ax,B
div_by 3

neg ax ;H = (15 - G - D + B + 19*A) % 30
add ax,15
add ax,B
sub ax,D
push ax
mov ax,A
mov bl,19
mul bl
pop bx
add ax,bx
div_by 30
mov H,dx

mov ax,C ;J = C / 4
div_by 4 ;K = C % 4

shl ax,1 ;M = (32 - H - K + 2*J + 2*E) % 7
sub ax,dx
mov bx,E
shl bx,1
add ax,bx
sub ax,H
add ax,32
div_by 7
mov M,dx

mov bx,11 ;N = (22*M + 11*H + A) / 451
mov ax,H
mul bx
mov cx,ax
shl bx,1
mov ax,M
mul bx
add ax,cx
add ax,A
div_by 451

mov bl,-7 ;P = 114 - 7*N + M + H
imul bl
add ax,114
add ax,M
add ax,H

div_by 31 ;month = P / 31
inc dx ;day = (P % 31) + 1
xchg ax,dx ;AX = day, DX = month

cmp dx,3
jne month4
lea si,March
jmp short print_month
month4: lea si,April

print_month: call dstring

call decout ;print the day

mov al,CR
call stdout
mov al,LF
call stdout

exit: int 20h

main ENDP

;---------------------------------------------------------------------
;STDOUT -- Display a character to the screen
;
;Upon entry, the character to be displayed is in AL

stdout PROC NEAR

push ax
push dx
mov dl,al
mov ah,2
int 21h
pop dx
pop ax
ret

stdout ENDP

;---------------------------------------------------------------------
;DSTRING -- display an ASCIIZ string
;
;Upon entry, DS:SI points to the string

dstring PROC NEAR

push ax
push si

cld

dstring1: lodsb
or al,al
jz dstring2
call stdout
jmp short dstring1

dstring2: pop si
pop ax
ret

dstring ENDP

;---------------------------------------------------------------------
;DECOUT -- prints a 16-bit binary number in AX, converts it to
; ASCII decimal form and displays it on the screen
;
;Upon entry, the number to be displayed is in AX

decout PROC NEAR

push ax
push bx
push cx
push dx

xor cx,cx ;counts digits to print
mov bx,10

decout1: inc cx ;increment counter
xor dx,dx ;prepare to divide
div bx ;divide by ten
push dx ;push remainder
or ax,ax ;is the quotient zero?
jnz decout1 ;if not, more numbers to convert

decout2: pop ax ;retrieve digit from stack
add al,'0' ;convert to ASCII
call stdout ;print the character
loop decout2 ;do all of the digits

pop dx
pop cx
pop bx
pop ax
ret

decout ENDP

;---------------------------------------------------------------------

CODE ENDS

END start