[Return to Main Page]

Enhanced Day of the Week by W.J. Brier
[Up to Source Code Repository]


Enhanced Day of the Week

This is an alternative to Paul Guertin's Day of the Week program. It is longer but has the advantage of supporting a wider range of dates.
By W.J. Brier, 1 March 2008.

;
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;*                                                                             *
;*                          COMPUTE THE DAY OF WEEK                            *
;*                                                                             *
;*                         by W.J. Brier, March 2008                           *
;*                                                                             *
;* This 6502 assembly language program calculates the day of the week from any *
;* calendar date from September 14, 1752 to December 31, 9999.                 *
;*                                                                             *
;* --------------------------------------------------------------------------- *
;*                                                                             *
;* Copyright (C)2008 by W.J. Brier.  All rights reserved.  Permission is here- *
;* by granted to copy and redistribute this software,  provided this copyright *
;* notice remains in the source code and proper attribution is given.  Any re- *
;* distribution must be at no charge to the end user.  This code  MAY  NOT  be *
;* incorporated into any package intended for sale unless  written  permission *
;* has been given by the author.                                               *
;*                                                                             *
;* THERE IS NO WARRANTY OF ANY KIND WITH THIS SOFTWARE.  It's free,  so  don't *
;* look a gift horse in the mouth.                                             *
;*                                                                             *
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;
;
;	Calling Syntax:
;
;	ldx #<date            ;starting address of..,
;	ldy #>date            ;date data
;	jsr cdow              ;this subroutine
;	sta dow               ;day of week returned in .A
;
;	.X and .Y are preserved.
;
;	The information at DATE must be in the following format:
;
;	Offset   Data
;	--------------------------------------------------------------
;	  $00    Year MSB.  For example, if the year is 2008 then this
;	         value would be $07.
;
;	  $01    Year LSB.  For example, if the year is 2008 then this
;	         value would be $D8.
;
;	  $02    Month, ranging from $01 to $0C (12).
;
;	  $03    Date, ranging from $01 to $1F (31).
;	--------------------------------------------------------------
;
;	Upon return, .A will contain the day of the week in the range $01-$07,
;	with $01 being Sunday.  Execution time will typically be 4150 clock
;	cycles, depending on the supplied values.  No range checking is perf-
;	ormed.  A bogus date will produce a bogus result.
;
;===============================================================================
;
;DECLARATIONS
;
_origin_ =$02000               ;assembly address
;
zpptr    =$10                  ;working ZP pointer
;
;	--------------------------------------------------------
;	Redefine the above assignments to suit your application.
;	--------------------------------------------------------
;
dayswk   =7                    ;days in a week
march    =$03                  ;March in binary
s_bits   =8                    ;number of bits in a byte
s_byte   =1                    ;size of a byte or char
s_date   =4                    ;size of the input date
s_dword  =4                    ;size of a double word
s_word   =2                    ;size of a word
y2fac    =4                    ;Y2 computation factor
y3fac    =100                  ;Y3 computation factor
y4fac    =400                  ;Y4 computation factor
;
;===============================================================================
;
;COMPUTE DAY OF WEEK
;
         *=_origin_            ;set program counter
;
cdow     stx zpptr             ;save pointer to...
         sty zpptr+1           ;date info
         ldy #s_date-1         ;bytes in date -1
;
cdow01   lda (zpptr),y         ;copy user's date...
         sta userdate,y        ;into our storage
         dey
         bpl cdow01
;
         lda month             ;month
         ldx yearlo            ;year LSB
         ldy yearhi            ;year MSB
         pha                   ;save month
         cmp #march            ;month March or later?
         bcs cdow03            ;yes, no year adjustment
;
         txa                   ;year LSB
         sec
         sbc #1                ;move back a year
         bcs cdow02
;
         dey                   ;adjust MSB
;
cdow02   tax                   ;hold LSB
;
cdow03   stx y1                ;save Y1
         sty y1+1
;
;	------------
;	compute Y1/4
;	------------
;
         jsr stafaca           ;store Y1 in accummulator #1
         ldx #<y2fac           ;4
         ldy #>y2fac
         jsr stafacb           ;copy to accummulator #2
         jsr dpdiv             ;Y2=Y1/4
         stx y2                ;store
         sty y2+1
;
;	---------------
;	compute Y1/100)
;	---------------
;
         jsr stay1fac          ;copy Y1 to accummulator #1
         ldx #<y3fac
         ldy #>y3fac
         jsr stafacb           ;copy to accummulator #2
         jsr dpdiv             ;Y3=Y1/100
         stx y3                ;store
         sty y3+1
;
;	--------------
;	compute Y1/400
;	--------------
;
         jsr stay1fac
         ldx #<y4fac
         ldy #>y4fac
         jsr stafacb           ;copy to accummulator #2
         jsr dpdiv             ;Y4=Y1/400
         stx y4                ;store
         sty y4+1
;
;	-------------
;	combine terms
;	-------------
;
         clc
         lda y1                ;Y1
         adc y2                ;Y2
         sta acm1
         lda y1+1
         adc y2+1
         sta acm1+1
         sec
         lda acm1
         sbc y3                ;Y3
         sta acm1
         lda acm1+1
         sbc y3+1
         sta acm1+1
         clc
         lda acm1
         adc y4                ;Y4
         sta acm1
         lda acm1+1
         adc y4+1
         sta acm1+1
         pla                   ;get month
         tax                   ;change 1-12 to...
         dex                   ;0-11
         clc
         lda acm1              ;combined terms
         adc dowmctab,x        ;month comp factor
         bcc cdow04
;
         inc acm1+1
;
cdow04   sta acm1
         clc
         lda date              ;date
         adc acm1              ;last term
         bcc cdow05
;
         inc acm1+1
;
cdow05   sta acm1
         ldx #<dayswk          ;number of days in a week
         ldy #>dayswk
         jsr stafacb           ;copy to accummulator #2
         jsr dpdiv             ;ACM1=ACM1 mod 7
         adc #1                ;0-6 --> 1-7...
;
;	-------------------------------------------------------
;	remove the above ADC #1 instruction for a 0-6 DOW range
;	-------------------------------------------------------
;
         ldx zpptr             ;restore
         ldy zpptr+1           ;likewise
         rts                   ;return day of week in .A
;
;================================================================================
;
;DOUBLE-PRECISION DIVISION
;
;	-----------------------------------------
;	acm1 = 16 bit dividend
;	acm2 = 16 bit divisor
;	-----------------------------------------
;	acm1 = 16 bit quotient
;	.A   = remainder
;	.X   = quotient LSB
;	.Y   = quotient MSB
;
;	The remainder is also available in acm1+2.
;
;	No check is made for division by zero.
;	------------------------------------------
;
dpdiv    lda #0
         sta acm1+s_word       ;clear dividend hi bits
         sta acm1+s_word+s_byte
         ldx #s_bits*s_word    ;bits to process
         clc
;
dpdiv01  rol acm1              ;rotate dividend
         rol acm1+s_byte
         rol acm1+s_word
         rol acm1+s_word+s_byte
         sec
         lda acm1+s_word
         sbc acm2              ;subtract divisor
         tay
         lda acm1+s_word+s_byte
         sbc acm2+s_byte
         bcc dpdiv02
;
         sty acm1+s_word       ;save partial quotient
         sta acm1+s_word+s_byte
;
dpdiv02  dex
         bne dpdiv01           ;next
;
         rol acm1              ;rotate in last carry to...
         rol acm1+s_byte       ;finish quotient
         lda acm1+s_word       ;get remainder LSB
         ldx acm1              ;get quotient LSB
         ldy acm1+s_byte       ;get quotient MSB
         rts
;
;================================================================================
;
;STORE Y1 INTO ACCUMMULATOR #1
;
stay1fac ldx y1
         ldy y1+1
;
;================================================================================
;
;STORE INTO ACCUMMULATOR #1
;
stafaca  stx acm1
         sty acm1+1
         rts
;
;================================================================================
;
;STORE INTO ACCUMMULATOR #2
;
stafacb  stx acm2
         sty acm2+1
         rts
;
;===============================================================================
;
;COMPENSATION TABLE
;
dowmctab .byte 0               ;January
         .byte 3               ;February
         .byte 2               ;March
         .byte 5               ;April
         .byte 0               ;May
         .byte 3               ;June
         .byte 5               ;July
         .byte 1               ;August
         .byte 4               ;September
         .byte 6               ;October
         .byte 2               ;November
         .byte 4               ;December
;
;===============================================================================
;
;WORKING STORAGE
;
acm1     *=*+s_dword           ;accummulator #1
acm2     *=*+s_word            ;accummulator #2
y1       *=*+s_word            ;adjusted year (Y1)
y2       *=*+s_word            ;Y1/4
y3       *=*+s_word            ;Y1/100
y4       *=*+s_word            ;Y1/400
;
;	-------------------------------------------------------------
;	The above locations should be defined on page zero if room is
;	available.  Execution time will be reduced about 20 percent.
;	-------------------------------------------------------------
;
userdate *=*+s_date            ;input date storage...
;
yearhi   =userdate             ;year MSB
yearlo   =yearhi+s_byte        ;year LSB
month    =yearlo+s_byte        ;month
date     =month+s_byte         ;date
;
;===============================================================================
	.end
Last page update: March 1, 2009.