Obsah / Utility / CALENDAR / Konverze data a času na absolutní čas
Zdrojový kód:
INCLUDE\UTIL\CALENDAR.INC, UTIL\CALENDAR.ASM
Konverze data
a času na absolutní čas
; -----------------------------------------------------------------------------
; Convert date-time to absolute time
; -----------------------------------------------------------------------------
; INPUT: EBX = date-time structure (see DATETIME)
; OUTPUT: EDX:EAX = absolute time (100-nanoseconds from 1/1/1 CE 0:00)
; NOTES: Entries are taken as signed and their overlaps are accounted.
; Only time and date entries are used. Flags, week, day in year
; and day of week are ignored.
; Takes 70 ns on 1.6 GHz CPU.
; -----------------------------------------------------------------------------
|
Funkce DateTimeToAbs
převede datum a čas z rozloženého tvaru na absolutní čas.
Registr EBX obsahuje na vstupu funkce ukazatel na strukturu
DATETIME. Ze struktury jsou použity pouze položky data a času.
Položky den v týdnu, den v roce, číslo týdne a příznaky
jsou ignorovány. Položky jsou interpretovány jako čísla se
znaménkem, případné přesahy hodnot jsou přeneseny do
vyšších řádů. Funkce navrací v registrech EDX:EAX
absolutní čas jako násobek 100 nanosekund od 0:00:00 hodin 1.
ledna roku 1 n.l.
; On whole function: ESI = date-time structure, EBP:EDI = accumulator.
; ------------- Push registers
DateTimeToAbs: push ebx ; push EBX
push ecx ; push ECX
push esi ; push ESI
push edi ; push EDI
push ebp ; push EBP
mov esi,ebx ; ESI <- date-time structure
|
Na začátku funkce
jsou uchovány registry EBX, ECX, ESI, EDI a EBP. Do registru ESI
je uložen ukazatel na strukturu DATETIME. Uvnitř funkce budou
použity registry EBP:EDI jako střadač výsledku.
; ------------- Convert second to 100-nanoseconds (-> EBP:EDI)
movsx eax,byte [esi+DATETIME_Sec] ; EAX <- second
mov ecx,10000000 ; ECX <- 100-nsec per second
imul ecx ; EAX <- recalc seconds to 100-nanosec
xchg eax,edi ; EDI <- accumulator LOW
mov ebp,edx ; EBP <- accumulator HIGH
|
Do registru EAX se
načte počet sekund. Je přitom počítáno s možným
přetečením hodnoty nad nebo pod platnou mez, proto se
používají operace se znaménkem. Vynásobením číslem
10000000 jsou sekundy převedeny na násobek stovek nanosekund a
uchovány do registrů EBP:EDI.
; ------------- Add nanosecond (-> EBP:EDI, ECX <- 0)
mov eax,1374389535 ; EAX <- 2000000000h/100 (rounded up)
imul dword [esi+DATETIME_NSec] ; EDX:EAX <- (nsec/100) << 37
sar edx,5 ; EDX <- nsec/100
mov eax,edx ; EAX <- nsec/100
shr eax,31 ; EAX <- signum bit (0 or 1)
add eax,edx ; EAX <- nsec/100 + signum correction
cdq ; EDX:EAX <- nsec/100
add edi,eax ; EDI <- add to accumulator LOW
adc ebp,edx ; EBP <- add to accumulator HIGH
|
Struktura DATETIME
obsahuje položku nanosekund, kterou je potřeba převést na
stovky nanosekund. Namísto dělení číslem 100 se použije
rychlejší operace násobení převrácenou hodnotou čísla,
tedy číslem 2000000000h/100 (zaokrouhleno nahoru). Po
vynásobení a posunu o 5 bitů doprava se přičtením
znaménkového bitu provede oprava hodnoty pro záporná čísla.
Výsledek se přičte ke střadači EBP:EDI.
; ------------- Add hour and minute (-> EBP:EDI)
movsx eax,byte [esi+DATETIME_Hour] ; EAX <- hour
imul eax,byte 60 ; EAX <- minutes
movsx ecx,byte [esi+DATETIME_Min] ; ECX <- minute
add eax,ecx ; EAX <- hour + minute
mov ecx,60*10000000 ; ECX <- 100-nsec per minute
imul ecx ; recalc minutes to 100-nanoseconds
add edi,eax ; EDI <- add to accumulator LOW
adc ebp,edx ; EBP <- add to accumulator HIGH
|
Dále budou
započítány položky hodiny a minuty. Do registru EAX je
načtena položka hodin. Vynásobením číslem 60 jsou hodiny
přepočítány na minuty. Po přičtení položky minut je
součet vynásoben číslem 60*10000000 a tím je převeden na
stovky nanosekund a poté přičten ke střadači výsledku
EBP:EDI.
; ------------- Convert date to absolute day
mov ecx,[esi+DATETIME_Date]
mov al,cl ; AL <- day
mov dl,ch ; DL <- month
sar ecx,16 ; CX <- year
call DateToAbsDay ; recalc date to absolute day
; ------------- Convert days to minutes (-> EDX:EAX)
mov ecx,24*60 ; ECX <- minutes per day
imul ecx ; EDX:EAX <- recalc days to minutes
|
Ze struktury DATETIME
jsou načteny položky data (den, měsíc a rok) a volámím
funkce DateToAbsDay jsou přepočteny na absolutní datum s
počátkem 1. ledna roku 1 n.l. Vynásobením číslem 24*60 jsou
dny přepočteny na minuty.
; ------------- Convert minutes to 100-nanoseconds (-> EDX:EAX)
xchg eax,ebx ; EBX <- store minutes LOW
xchg eax,edx ; EAX <- minutes HIGH
mov ecx,60*10000000 ; ECX <- 100-nanoseconds per minute
imul ecx ; recalc minutes HIGH to 100-nanosec
add ebp,eax ; add minutes HIGH to accumulator HIGH
xchg eax,ebx ; EAX <- minutes LOW
mul ecx ; recalc minutes LOW to 100-nanosec
add eax,edi ; add accumulator LOW to minutes LOW
adc edx,ebp ; add accumulator HIGH to minutes LOW
; ------------- Pop registers
pop ebp ; pop EBP
pop edi ; pop EDI
pop esi ; pop ESI
pop ecx ; pop ECX
pop ebx ; pop EBX
ret
|
Minuty (z
absolutního čísla dne) se přepočtou na stovky nanosekund
vynásobením číslem 60*10000000 a výsledek se přičte ke
střadači výsledku. Minuty jsou 64-bitovým číslem, proto se
násobení provede ve dvou krocích, pro nižší a vyšší
dvojslovo. K výsledku se přičte hodnota střadače a navrátí
se jako výsledek funkce.
Obsah / Utility / CALENDAR / Konverze data a času na absolutní čas