Page 1 sur 1

Procedure Année Bissextile en ASM ( IsLeapYear() )

Publié : ven. 22/nov./2013 15:40
par Mesa

Code : Tout sélectionner

;Traduction du code ici http://mikhajduk.houa.org/EN/index.php?f=Links
;Translation from http://mikhajduk.houa.org/EN/index.php?f=Links

;{ Français
; Depuis l'ajustement du calendrier grégorien, sont bissextiles les années :
; 
;     soit divisibles par 4 mais non divisibles par 100 ;
;     soit divisibles par 400.
; 
; Donc, inversement, ne sont pas bissextiles les années :
; 
;     soit non divisibles par 4 ;
;     soit divisibles par 100, mais pas par 400.

Procedure.l Bissextile(annee.l, option.l)
; DWORD IsLeapYear(DWORD année, DWORD option)
;
; Cette fonction détermine si une année est bissextile dans le calendrier choisi.
;
; Paramètres:
;	annee - année,
;	option - Calendrier (0 - Julien, 1 - Gregorien).
;
; Les valeurs retournées:
;	* 1 si l'année est bissextile 
; * 0 sinon,
;	* -1 pour les paramètres non valides.
;

 EnableASM
; PUSHFD
; PUSH	ebx edx

checkparametres:
TEST	option, -2       ; 0 <= Gregorian <= 1
JNZ	l_bissextile_erreur						

isynegative:
MOV	eax, annee					; eax := Y =year

TEST	eax, eax 
JZ	l_bissextile_erreur        
JNS	l_bissextile_quelcalendrier 
; eax < 0 (Y < 0)

INC	eax						; eax := eax + 1
NEG	eax						; eax := -eax = -(Y + 1) = -Y - 1 =
;      = |Y| - [Y < 0] = Y'

quelcalendrier:
CMP	option, 0  
JE	l_bissextile_mod4

gregorien:
XOR	edx, edx					; eax := E(eax / 100) = E(Y' / 100)
MOV	ecx, 100					; edx := eax mod 100 = Y' mod 100
DIV	ecx						    ; div=(edx:eax)/ecx -> Quotient=eax  Reste=edx
                      ; Long .l 4 octets -2147483648 à +2 147 483 647 

TEST	edx, edx
JZ	l_bissextile_mod4

MOV	eax, edx					; eax := edx = Y' mod 100
; 
; {(Y' mod 100) mod 4 = Y' mod 4}

mod4:
SHR	eax, 1						; eax := E(eax / 2); CF := eax mod 2
JC	l_bissextile_resultat						; 

SHR	eax, 1						; eax := E(eax / 2); CF := eax mod 2
JMP	l_bissextile_resultat						;

erreur:
MOV	eax, -1
JMP	l_bissextile_fin

resultat:
SETNC	al						; eax := not CF
MOVZX	eax, al						

fin:
; POP	edx ebx
; POPFD


DisableASM

ProcedureReturn
EndProcedure
;}

;{ English
Procedure.l IsLeapYear(year.l, option.l)
; DWORD IsLeapYear(DWORD Y, DWORD Gregorian)
;
; This function determines if the given year is leap in the chosen calendar.
;
; Parameters:
;	Y - year,
;	Gregorian - chosen calendar (0 - Julian, 1 - Gregorian).
;
; Returned values:
;	* 1 if the year Y is leap, 0 - in opposite case,
;	* -1 for the invalid parameters.
;

 EnableASM
; PUSHFD
; PUSH	ebx edx

checkparameters:
TEST	option, -2       ; 0 <= Gregorian <= 1
JNZ	l_isleapyear_error						

isynegative:
MOV	eax, year					; eax := Y =year

TEST	eax, eax 
JZ	l_isleapyear_error        
JNS	l_isleapyear_checkcalendar 
; eax < 0 (Y < 0)

INC	eax						; eax := eax + 1
NEG	eax						; eax := -eax = -(Y + 1) = -Y - 1 =
;      = |Y| - [Y < 0] = Y'

checkcalendar:
CMP	option, 0  
JE	l_isleapyear_mod4

gregorian:
XOR	edx, edx					; eax := E(eax / 100) = E(Y' / 100)
MOV	ecx, 100					; edx := eax mod 100 = Y' mod 100
DIV	ecx						    ; div=(edx:eax)/ecx -> Quotient=eax  Reste=edx
                      ; Long .l 4 octets -2147483648 à +2 147 483 647 

TEST	edx, edx
JZ	l_isleapyear_mod4

MOV	eax, edx					; eax := edx = Y' mod 100
; 
; {(Y' mod 100) mod 4 = Y' mod 4}

mod4:
SHR	eax, 1						; eax := E(eax / 2); CF := eax mod 2
JC	l_isleapyear_result						; 

SHR	eax, 1						; eax := E(eax / 2); CF := eax mod 2
JMP	l_isleapyear_result						;

error:
MOV	eax, -1
JMP	l_isleapyear_theend

result:
SETNC	al						; eax := not CF
MOVZX	eax, al						

theend:
; POP	edx ebx
; POPFD


DisableASM

ProcedureReturn
EndProcedure

;}


Debug bissextile(2000,1)
Debug bissextile(2001,1)

Debug IsLeapYear(2000,1)
Debug IsLeapYear(2001,1)

; Macro from PAPIPP http://www.purebasic.fr/french/viewtopic.php?f=6&t=13296
; Macro _AN_BIS (x); cette macro définie si une année x est bissextile ou non 
; ((Not((x%4)<>0)) & ((1-(Not((x%100)<>0)) ) | (Not(((x>>2)%100)<>0)) ) )
; EndMacro

; bissextile =  2016, 2008, 2000
;  leap year =  2016, 2008, 2000

Mesa.

Re: Procedure Année Bissextile en ASM

Publié : sam. 23/nov./2013 15:50
par PAPIPP
Bonjour Mesa
Merci pour l'option en ASM
Voici une correction pour PB520 et PB521 de la MACRO _AN_BIS avec bool()

Code : Tout sélectionner

; Macro from PAPIPP http://www.purebasic.fr/french/viewtopic.php?f=6&t=13296
Macro _AN_BIS(x); cette macro définie si une année x est bissextile ou non
  ((Bool(Not Bool((x%4)<>0))) & ((1-Bool(Not Bool((x%100)<>0)) ) | Bool(Not Bool(((x>>2)%100)<>0)) ) )
EndMacro
Debug _AN_bis(2000)
Debug _AN_bis(1900)
Debug _an_bis(1932)
A+