Assembly code snippets
Details
Title | Day of Week |
---|---|
Author | lingo12 |
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 ;
; 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 ;