
Полезные функции для работы с датами на Ассемблере

Полезные функции для работы с датами на Ассемблере
Из разных источников насобирал различные полезные функции для работы с датами на Ассемблере. Преимущества их в том, что они работают очень быстро, хорошо оптимизированы и позволяют обходиться вообще без вызова системных функций. Все функции самодостаточные и не требуют для работы каких-либо дополнительных данных.
Функция для определения является ли год високосным. Как известно, високосным годом является такой год, продолжительность которого равна 366 дням - на одни сутки больше продолжительности обычного. Год является високосным в двух случаях: либо он кратен 4, но при этом не кратен 100, либо кратен 400. Год не является високосным, если он не кратен 4, либо он кратен 100, но при этом не кратен 400.
Code (Assembler) : Убрать нумерацию
- ;-------------------------------------------------------------
- ; Функция определения является ли год високосным
- ;-------------------------------------------------------------
- ; Параметры: год
- ; На выходе:
- ; EAX = 1 - год високосный
- ; EAX = 0 - год невисокосный
- ;-------------------------------------------------------------
- proc IsLeapYear year:DWORD
- push edx ebx
- xor edx,edx
- mov eax,[year]
- mov ebx,100
- div ebx
- or edx,edx
- jz @f
- mov eax,edx
- @@:
- shr eax,1
- jc @f
- shr eax,1
- @@:
- setnc al
- movzx eax,al
- pop ebx edx
- ret
- endp
Code (Assembler) : Убрать нумерацию
- ;-------------------------------------------------------------
- ; Функция вычисления дня недели для любой даты
- ; Автор: Lingo
- ;-------------------------------------------------------------
- ; На основе алгоритма 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;
- ; }
- ;-------------------------------------------------------------
- ; Параметры: год, месяц, день
- ; На выходе:
- ; EAX = день недели (0-6, 0 = воскресенье)
- ;-------------------------------------------------------------
- proc DayOfWeek year:DWORD, month:DWORD, day:DWORD
- push ebx ecx edx
- mov ecx,[month]
- mov edx,[year]
- cmp ecx,3
- sbb edx,0
- mov ecx,[.monthdata+ecx*4-4]
- mov eax,edx
- imul edx,0A3D8h
- shr edx,22
- add ecx,[day]
- add ecx,eax
- shr eax,2
- add eax,ecx
- sub eax,edx
- shr edx,2
- add eax,edx
- mov ecx,eax
- mov edx,24924925h
- mul edx
- mov eax,ecx
- lea ecx,[edx+edx*2]
- lea edx,[ecx+edx*4]
- sub eax,edx
- pop edx ecx ebx
- ret
- .monthdata dd 0,3,2,5,0,3,5,1,4,6,2,4
- endp
Code (Assembler) : Убрать нумерацию
- ;-------------------------------------------------------------
- ; Функция вычисления порядкового номера любого дня в году
- ; Автор: micmic
- ;-------------------------------------------------------------
- ; Параметры: год, месяц, день
- ; На выходе:
- ; EAX = порядковый номер дня (1-366)
- ;-------------------------------------------------------------
- proc DayOfYear year:DWORD, month:DWORD, day:DWORD
- push ebx ecx edx
- mov eax,[year]
- mov ecx,[month]
- mov edx,[day]
- dec ecx
- mov ebx,ecx
- imul ecx,30
- test ebx,9
- jnz @f
- dec ecx
- @@:
- shr ebx,1
- jnz @f
- add ecx,2
- @@:
- add ecx,ebx
- cmp ecx,32
- lea ecx,[ecx+edx-1]
- jna .loc_done
- test eax,3
- jnz .loc_done
- xor edx,edx
- mov ebx,100
- div ebx
- cmp edx,0
- jnz @f
- and eax,3
- jnz .loc_done
- @@:
- inc ecx
- .loc_done:
- mov eax, ecx
- pop edx ecx ebx
- ret
- endp
Code (Assembler) : Убрать нумерацию
- ;-----------------------------------------------------------
- ; Функция перевода TIMESTAMP в дату
- ; by ManHunter / PCL
- ; http://www.manhunter.ru
- ;-----------------------------------------------------------
- ; Параметры:
- ; dTimestamp - значение TIMESTAMP в секундах от 01.01.1900
- ; lpSTime - указатель на структуру SYSTEMTIME
- ; На выходе:
- ; заполненная структура SYSTEMTIME
- ;-----------------------------------------------------------
- proc timestamp_to_date dTimestamp:DWORD, lpSTime:DWORD
- locals
- ftime FILETIME
- endl
- pusha
- mov eax,[lpSTime]
- mov [eax+SYSTEMTIME.wYear],1900
- mov [eax+SYSTEMTIME.wMonth],1
- mov [eax+SYSTEMTIME.wDay],1
- mov [eax+SYSTEMTIME.wHour],0
- mov [eax+SYSTEMTIME.wMinute],0
- mov [eax+SYSTEMTIME.wSecond],0
- lea ebx,[ftime]
- invoke SystemTimeToFileTime,eax,ebx
- mov eax,[dTimestamp]
- xor edx,edx
- mov ecx,989680h
- mul ecx
- add [ftime.dwLowDateTime],eax
- adc [ftime.dwHighDateTime],edx
- invoke FileTimeToSystemTime,ebx,[lpSTime]
- popa
- ret
- endp
Code (Assembler) : Убрать нумерацию
- ;-----------------------------------------------------------
- ; Функция перевода даты в TIMESTAMP
- ; by ManHunter / PCL
- ; http://www.manhunter.ru
- ;-----------------------------------------------------------
- ; Параметры:
- ; lpSTime - указатель на заполненную структуру SYSTEMTIME
- ; На выходе:
- ; EAX = значение TIMESTAMP в секундах от 01.01.1900
- ;-----------------------------------------------------------
- proc date_to_timestamp lpSTime:DWORD
- locals
- ftime FILETIME
- ztime SYSTEMTIME
- dTimestamp dd ?
- endl
- pusha
- lea ebx,[ftime]
- invoke SystemTimeToFileTime,[lpSTime],ebx
- push [ftime.dwHighDateTime]
- push [ftime.dwLowDateTime]
- lea eax,[ztime]
- mov [eax+SYSTEMTIME.wYear],1900
- mov [eax+SYSTEMTIME.wMonth],1
- mov [eax+SYSTEMTIME.wDay],1
- mov [eax+SYSTEMTIME.wHour],0
- mov [eax+SYSTEMTIME.wMinute],0
- mov [eax+SYSTEMTIME.wSecond],0
- invoke SystemTimeToFileTime,eax,ebx
- pop eax
- sub eax,[ftime.dwLowDateTime]
- pop edx
- sbb edx,[ftime.dwHighDateTime]
- mov ecx,989680h
- div ecx
- mov [dTimestamp],eax
- popa
- mov eax,[dTimestamp]
- ret
- endp
Code (Assembler) : Убрать нумерацию
- stime SYSTEMTIME
- ftime FILETIME
- ...
- ; Проверяемая дата
- mov [stime.wYear],2023
- mov [stime.wMonth],2
- mov [stime.wDay],30 ; <--- ошибочное значение
- invoke SystemTimeToFileTime,stime,ftime
- or eax,eax
- ; EAX=1 - дата корректная
- ; EAX=0 - дата неправильная
- jz incorrect_date
Code (Assembler) : Убрать нумерацию
- ;-----------------------------------------------------------
- ; Функция получения количества дней в меняце
- ; by ManHunter / PCL
- ; https://www.manhunter.ru
- ;-----------------------------------------------------------
- ; Параметры:
- ; dYear - год
- ; dMonth - месяц
- ; На выходе:
- ; EAX = количество дней в месяце
- ;-----------------------------------------------------------
- proc days_in_month dYear:DWORD,dMonth:DWORD
- locals
- stime SYSTEMTIME
- ftime FILETIME
- endl
- pusha
- lea esi,[stime]
- lea edi,[ftime]
- mov eax,[dYear]
- mov [esi+SYSTEMTIME.wYear],ax
- mov eax,[dMonth]
- mov [esi+SYSTEMTIME.wMonth],ax
- mov ebx,32
- @@:
- dec ebx
- or ebx,ebx
- jz @f
- mov [esi+SYSTEMTIME.wDay],bx
- invoke SystemTimeToFileTime,esi,edi
- or eax,eax
- jz @b
- @@:
- mov [esp+28],ebx
- popa
- ret
- endp
Уже известный вам программист Николай Гайдук разработал замечательную библиотеку календарных функций для юлианского и григорианского календарей. Она написана на FASM, отлично документирована, и дает программисту многие возможности: обслуживает даты с периода длиной сверх 11 миллионов лет (с 1 января 5843880 года до н.э. по 3 августа 5915100 года для юлианского календаря, с 30 декабря 5844001 года до н.э. по 17 января 5915222 года для григорианского календаря), свободная конверсия дат между календарями юлианском и григорианском в упомянутом периоде, определение дня недели для данной даты, вычисление номера дня в году для данных номеров месяца и дня в месяце, определение високосности года в данном календаре, вычисление "абсолютного" номера дня соответствующего данной дате, благодаря чему можно легко рассчитывать количество дней между двумя датами. Скачать библиотеку с исходником и документацией можно с офсайта или по ссылке ниже.
Если у вас есть еще какие-нибудь интересные функции для работы с календарем или датами, то оставляйте в комментариях, я с удовольствием дополню статью.
Просмотров: 8816 | Комментариев: 4

Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
ManHunter
(24.11.2019 в 16:41):
Ну так подключи, в чем проблема.

Олег
(28.09.2019 в 19:23):
Не работает.
Не подключены библиотеки
Не подключены библиотеки

ManHunter
(21.01.2016 в 00:19):
Написал и добавил функцию перевода TIMESTAMP в дату и обратную ей функцию перевода даты в TIMESTAMP. Архив с исходниками обновлен.

Grey
(04.06.2014 в 11:38):
Спасибо.

Добавить комментарий
Заполните форму для добавления комментария
