Assembly code snippets

Back to the snippets overview

Details

TitleDay of Week
Authorlingo12
Submitted by:bitRAKE
Date added:2003-05-10 05:14:04
Date modified:2003-05-10 05:14:04

Comments

An incredible optimization of a very useful function.

See explaination here:
http://board.win32asmcommunity.net/showthread.php?s=&postid=102206#post102206

Snippet

; Work out what the day of the week is for a given date
; Speed optimized x86 assembly (PIII) by Lingo
;
; C Algorithm by Tomohiko Sakamoto
; int dayofweek(int d, int m, int y) {
;   static int t[] = { 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4 };
;   y -= m < 3;
;   return ( y + y/4 - y/100 + y/400 + t[m-1] + d) % 7;
; }
; year  = [0, 9999+]
; month = [1, 12]
; day   = [1, 31]

DayOfWeekL  PROTO year:DWORD, month:DWORD, day:DWORD

.data
monthdata   dword 0,3,2,5,0,3,5,1,4,6,2,4
.code
OPTION PROLOGUE:NONE              ; turn it off
OPTION EPILOGUE:NONE              ;
Align 16                          ; Align 16 before the proc
DayOfWeekL  PROC year:DWORD, month:DWORD, day:DWORD
  mov  ecx, [esp+8]               ; ecx=month
  mov  edx, [esp+4]           ; edx=year
  cmp  ecx, 3                     ; test if month is < 3
  sbb  edx, 0                     ; if month < 3 then dec edx->years
  mov  ecx, [monthdata + ecx*4-4] ; ecx-> monthdata[m-1]
  mov  eax, edx                   ; eax=edx=years
  imul edx, 0A3D8h                ; dividing edx=years by 100 == imul edx, 0A3D8h / shr edx, 22
  add  ecx, [esp+12]              ; add day; ecx= monthdata[m-1] + day
  add  ecx, eax                   ; ecx-> monthdata[m-1] + day + years
  shr  eax, 2                     ; eax= years/4
  add  eax, ecx                   ; eax= monthdata[m-1] + day + years + years/4
  mov  ecx, [esp]                 ; ecx->return address
  mov  [esp+12], ecx              ; ecx->return address to right place
  shr  edx, 22                    ; end of dividing ; edx=years/100
  sub  eax, edx                   ; eax= monthdata[m-1] +day + years + years/4 - years/100
  shr  edx, 2                     ; edx=years/400
  add  eax, edx                   ; eax= monthdata[m-1] +day + years + years/4 - years/100 + years/400
  mov  edx, 24924925h             ; dividing eax by 7 == mul edx, eax ; 24924925h=dword (1/7 * 2^35)
  mov  ecx, eax                   ; ecx= monthdata[m-1]  + day + years + years/4 - years/100 + years/400
  mul  edx                        ; dividing eax by 7 ->result in edx
  mov  eax, ecx                   ; eax= monthdata[m-1] + day + years + years/4 - years/100 + years/400
  lea  ecx, [edx+edx*2]           ; multiplying edx by 7 ->
  lea  edx, [ecx+edx*4]           ; ->result in edx
  add  esp, 3*4                   ; clearing the stack from 3 dword parameters
  sub  eax, edx                   ; eax= (monthdata[m-1] + day + years + years/4 - years/100 + years/400) % 7
  ret                             ; faster return then return 3*4
DayOfWeekL  ENDP                  ;
OPTION PROLOGUE:PROLOGUEDEF       ; turn back on the defaults
OPTION EPILOGUE:EPILOGUEDEF       ;