Tvůrce webu je i pro tebe! Postav třeba web. Bez grafika. Bez kodéra. Hned.
wz

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