DateToAbsDayNum en ASM (pour archive)

Pour discuter de l'assembleur
Mesa
Messages : 1097
Inscription : mer. 14/sept./2011 16:59

DateToAbsDayNum en ASM (pour archive)

Message par Mesa »

Code : Tout sélectionner

; DWORD DateToAbsDayNum(DWORD Y, DWORD M, DWORD D, DWORD Gregorian)
;
; This function calculates the absolute day number for the given date.
;
; Parameters:
;	Y - year,
;	M - month,
;	D - day,
;	Gregorian - chosen calendar (0 - Julian, 1 - Gregorian).
;
; Returned values:
;	* 1, 2, ..., 2^32-1 for the valid date in the chosen calendar,
;	* 0 for the invalid parameters.
;
;proc	DateToAbsDayNum, Y, M, D, Gregorian

Procedure.l DateToAbsDayNum( Y.l, M.l, D.l, Gregorian.l)
	;;PUSHFD
	;PUSH	ebx ecx edx
	Protected X.l
	
 EnableASM
	TEST	Gregorian, -2						; 0 <= Gregorian <= 1
	JNZ	l_datetoabsdaynum_error							;

	IsLeapYear(Y, Gregorian)				;
	CMP	eax, -1							; eax := IsLeapYear(Y, Gregorian)
	JE	l_datetoabsdaynum_error							;

									; Y <> 0

	;MOV	ebx, eax						; ebx := eax
	MOV X, eax
	
	MDToDayNum(M, D, X)				;ebx
	CMP	eax, -1							; eax := MDToDayNum(M, D, ebx) = n
	JE	l_datetoabsdaynum_error							;

	MOV	ecx, Y						;
	CMP	ecx, 0							; ecx := Y
	JG	l_datetoabsdaynum_calculatedaynum					;

	INC	ecx							; Y < 0
									; ecx := ecx + 1 = Y + 1 = Y + [Y < 0]

	calculatedaynum:
; 		Global k	= 30
;     Global J	= 194796		; The constants J and G are equal to the numbers of the complete years
; Global G	= 194800		; of the Julian and Gregorian calendars respectively contained in the 
				; time interval given by "Great Cycle" T.						
	ADD	ecx, 5843880; k*J					;
	
		CMP	Gregorian, 0					; ecx := ecx + kJ + k(G-J)[Gregorian = 1] =
		JE	l_datetoabsdaynum_yprim0						;      = Y + [Y < 0] + kJ + k(G-J)[Gregorian = 1] = Y'
		ADD	ecx, 120; k*(G-J)					; 
; Global k	= 30
; Global J	= 194796		; The constants J and G are equal to the numbers of the complete years
; Global G	= 194800		; of the Julian and Gregorian calendars respectively contained in the 
				; time interval given by "Great Cycle" T.

	yprim0:
		CMP	ecx, 0						;
		JNE	l_datetoabsdaynum_yprimpositive					; Y' = 0
		SUB	eax, 364					; eax := eax - 364 = n - 364
		JMP	l_datetoabsdaynum_theend						;

	yprimpositive:							; Y' > 0
								;
		DEC	ecx						; ecx := ecx - 1 = Y' - 1
		;MOV	ebx, eax					; ebx := eax = n
		MOV X, eax
		
		MOV	eax, 365					; eax := 365
		MUL	ecx						; eax := 365 * ecx = 365(Y' - 1);(EDX:EAX <- EAX * r/m32
		
	  SHR	ecx, 2						; ecx := E(ecx / 4) = E((Y' - 1) / 4)

		ADD	eax, ecx					; eax := eax + ecx = 365(Y' - 1) + E((Y' - 1) / 4)
		;ADD	eax, ebx					; eax := eax + ebx = eax + n =
		ADD	eax, X							;      = 365(Y' - 1) + E((Y' - 1) / 4) + n

		CMP	Gregorian, 0
		JZ	l_datetoabsdaynum_theend

	gregorian:
	;PUSH	eax						; X := eax
	MOV X, eax			    ; Sauvegarde de eax
;Debug X
		XOR	edx, edx					;
		MOV	eax, ecx					; eax := ecx = E((Y' - 1) / 4)
		MOV	ecx, 25						;
		DIV	ecx						; eax := E(eax / 25) = E(E((Y' - 1) / 4) / 25) =
		;      = E((Y' - 1) / 100)
		;Unsigned divide EDX:EAX by r/m32, with
    ;result stored IN EAX <- Quotient, EDX <- Remainder.

		MOV	ecx, eax					; ecx := eax = E((Y' - 1) / 100)
		;POP	eax						; eax := X = 365(Y' - 1) + E((Y' - 1) / 4) + n
    MOV eax, X
		

    SUB	eax, ecx					; eax := eax - ecx = 365(Y' - 1) + E((Y' - 1) / 4) + n -
									;                    - E((Y' - 1) / 100)

		SHR	ecx, 2						; ecx : = E(ecx / 4) = E(E((Y' - 1) / 100) / 4) =
									;       = E((Y' - 1) / 400)


		ADD	eax, ecx					; eax := eax + ecx = 365(Y' - 1) + E((Y' - 1) / 4) + n -
									;                    - E((Y' - 1) / 100) + E((Y' - 1) / 400)

		ADD	eax, 2						; eax := eax + 2 = 365(Y' - 1) + E((Y' - 1) / 4) + n -
									;                  - E((Y' - 1) / 100) + E((Y' - 1) / 400) + 2 =
									;                = N
	
		JMP	l_datetoabsdaynum_theend

		error:
		;Debug "err"
		XOR	eax, eax

	theend:

	;POP	edx ecx ebx
	;POPFD
DisableASM
ProcedureReturn 

EndProcedure

Debug DateToAbsDayNum( 2000, 1, 1, 1);Y.l, M.l, D.l, Gregorian.l
M.
Avatar de l’utilisateur
falsam
Messages : 7244
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: DateToAbsDayNum en ASM (pour archive)

Message par falsam »

Bonjour Mesa. Souci avec IsLeapYear(Y, Gregorian). Fonction inconnue.
Configuration : Windows 11 Famille 64-bit - PB 6.03 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
Mesa
Messages : 1097
Inscription : mer. 14/sept./2011 16:59

Re: DateToAbsDayNum en ASM (pour archive)

Message par Mesa »

Les 2 fonctions utilisées ont été postées :

isleapyear, c'est année bissextile
http://www.purebasic.fr/french/viewtopi ... 12&t=14097

et MDToDayNum, c'est date vers rang du jour, déjà postée aussi.

De toute façon, que j'arrive au bout de la traduction ou non, je posterai un thread avec toutes les procédures réunies (en 2014).

M.
Répondre