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

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

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

Message 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.
Dernière modification par Mesa le jeu. 19/déc./2013 19:01, modifié 4 fois.
PAPIPP
Messages : 534
Inscription : sam. 23/févr./2008 17:58

Re: Procedure Année Bissextile en ASM

Message 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+
Il est fort peu probable que les mêmes causes ne produisent pas les mêmes effets.(Einstein)
Et en logique positive cela donne.
Il est très fortement probable que les mêmes causes produisent les mêmes effets.
Répondre