Fonction HexaToDecimal()
Fonction HexaToDecimal()
Comme il n'y a pas beaucoup de code dans cette section, je vous propose (pour ceux qui veulent) de poster votre code asm pour créer une fonction qui va convertir une valeur hexadécimal (donc une chaine commençant par $) en une valeur décimal sur 32 bits.
- Le code devra ne devra être que de l'asm (pas de for i= ou des trucs dans le genre)
- Le format majuscule/minuscule de l'hexa devra être pris en compte
1 version avec la vérification du format hexa (c'est-à-dire on contrôle la présence du $ et que chaque caractère est bien un caractère hexa ainsi que la longueur de la chaine qui sera au max de 9 éléments)
1 variante sans vérification du format (sera donc plus rapide)
Si il y a une erreur, on retourne 0 (ou autre chose si vous avez une meilleur idée)
La rapidité à l'exécution est la chose primordiale.
une petite explication au début du code pour donner la méthode utilisée.
Ca vous dit ?
On pourra faire une librairie ensuite et y ajouter des fonctions
- Le code devra ne devra être que de l'asm (pas de for i= ou des trucs dans le genre)
- Le format majuscule/minuscule de l'hexa devra être pris en compte
1 version avec la vérification du format hexa (c'est-à-dire on contrôle la présence du $ et que chaque caractère est bien un caractère hexa ainsi que la longueur de la chaine qui sera au max de 9 éléments)
1 variante sans vérification du format (sera donc plus rapide)
Si il y a une erreur, on retourne 0 (ou autre chose si vous avez une meilleur idée)
La rapidité à l'exécution est la chose primordiale.
une petite explication au début du code pour donner la méthode utilisée.
Ca vous dit ?
On pourra faire une librairie ensuite et y ajouter des fonctions
-
- Messages : 4312
- Inscription : mer. 28/janv./2004 20:58
- Localisation : Clermont ferrand OU Olsztyn
- Contact :
Bonne idèe Denis
Excuse pour les explications... c'est 23 h 20 il faut que je dorme
Code : Tout sélectionner
Procedure ValHex(Chaine.s)
Valeur.l
MOV ecx,Chaine
CMP byte [ecx],'$'
JNZ NonChaineHexa
!LEA ebx,[TableValeur]
MOV edx,0
XOR eax,eax
!Encore:
INC ecx
MOV al,byte [ecx]
CMP al,0
JE FinChaineHexa
XLATB
CMP al,$FF
JE NonChaineHexa
ROL edx,4
ADD edx,eax
JMP Encore
!FinChaineHexa:
MOV Valeur,edx
ProcedureReturn Valeur
!NonChaineHexa:
ProcedureReturn 0
!TableValeur:
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $00,$01,$02,$03,$04,$05,$06,$07,$08,$09,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$0A,$0B,$0C,$0D,$0E,$0F,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$0A,$0B,$0C,$0D,$0E,$0F,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
EndProcedure
Debug ValHex("$10")
Debug ValHex("$1A0f")
Debug ValHex("10")
Debug ValHex("$1u0")
Salut Eric,
Quand j'ai vu ton code, je me suis dit tout de suite que l'on allait avoir du mal à faire plus rapide
Je mets ma version mais la mienne est 2 fois plus lente pour une chaîne courte et 2,5 plus lente pour une chaîne hexa de 8 caractères.
Le codage dans la table est sûrement la solution la plus rapide pour la conversion.
On gardera le meilleur
Quand j'ai vu ton code, je me suis dit tout de suite que l'on allait avoir du mal à faire plus rapide
Je mets ma version mais la mienne est 2 fois plus lente pour une chaîne courte et 2,5 plus lente pour une chaîne hexa de 8 caractères.
Le codage dans la table est sûrement la solution la plus rapide pour la conversion.
On gardera le meilleur
Code : Tout sélectionner
Procedure.l HexaDecimalToDecimal(Chaine.s)
; calcul de la valeur décimale d'une chaîne hexa
; le principe est celui des additions successives des valeurs de chaque caractère hexa
; en fonction de sa position dans la chaîne
; par exemple le nombre hexa $A0 vaut en décimal 160
; La décomposition de $A0 est
; A : 10 * 16^1 = 10 * 16 = 160
; 0 : 0 * 16^0 = 0 * 1 = 0
; Total : 160 + 0 = 160
;
; A vaut 10 en décimal et ce caractère est transformé en valeur décimale 10
; La chaîne hexa mesure sans le $ 2
; A étant le premier caractère hexa, il est à la position 2 dans la chaine en partant de la droite
; mais sa puissance de 16 est de 2-1 (16^1)
; je charge dans la table la puissance de 16 précalculée
; par exemple 16^0 correspond la valeur située à l'adresse de la table +0
; par exemple 16^1 correspond la valeur située à l'adresse de la table + 1*4 (*4 car la valeur
; codée est une valeur 32 bits donc sur 4 octets)
; par exemple 16^3 correspond la valeur située à l'adresse de la table + 3*4
; je multiplie cette puissance par la valeur correspondante au caractère
; le tout est stocké dans eax auquel on ajoute ensuite l'ancienne valeur de eax, résultat
; des précédants calculs
valeur.l
MOV ebx,Chaine
CMP byte [ebx],'$'
JNZ NonChaineHexa1
MOV ecx, 0 ; ecx à 0
INC ebx ; on pointe après le $
MOV eax, ecx ; eax à 0
LEA esi, [PuissanceHexa] ; esi = adresse de la 1er valeur de la table hexa
PUSH ebx ; sauvegarde afin de récupérer plus tard cette valeur
; calcul de la longueur de la chaine
!Compte:
MOV dl, [ebx]
TEST dl, dl
JZ FinComptage
INC cl
INC ebx
JMP Compte
!FinComptage:
POP ebx ; ebx = adresse du début de chaine après le $
DEC ecx ; ecx = exposant de la puissance du 1er caractère
JS NonChaineHexa1
CMP cl, 7 ; on termine si la chaine hexa > à 8 caractères
JA NonChaineHexa1
!DebutCalcul:
MOVZX edx, byte [ebx] ; dl = le caractère hexa
TEST dl, dl ; si = 0 on quite, fin de chaine
JZ Finchaine
!Minuscule?:
CMP dl, 'f'
JA NonChaineHexa1
CMP dl, 'a'
JB Majuscule?
ADD dl, -87 ; on ajuste pour partir à 10
!Calcul: ; résultat dans eax à chaque tour de boucle
PUSH eax ; sauvegarde temporaire de eax
MOV eax, [esi+(ecx*4)] ; la puissance de 16 correspondante à la position du caractère dans la chaine
MUL edx ; multiplication non signée de eax par edx, résultat dans eax
POP edx ; edx = ancienne valeur de eax
ADD eax, edx ; eax = résultat
INC ebx ; incrémentation du pointeur de chaine
DEC ecx ; décrémentation de l'exposant de la puissance de 16
JMP DebutCalcul
!Majuscule?:
CMP dl, 'F'
JA NonChaineHexa1
CMP dl, 'A'
JB Nombre?
ADD dl, -55 ; on ajuste pour partir à 10
JMP Calcul
!Nombre?:
CMP dl, '9'
JA NonChaineHexa1
CMP dl, '0'
JB NonChaineHexa1
ADD dl, -48 ; c'est un chiffre, on ajuste pour partir à 0 ('0' = 48)
JMP Calcul
!Finchaine:
ProcedureReturn
!PuissanceHexa:
!DD 1, 16, 256, 4096, 65536, 1048576, 16777216, 268435456
!NonChaineHexa1:
ProcedureReturn 0
EndProcedure
Debug HexaDecimalToDecimal("$")
Debug HexaDecimalToDecimal("$10")
Debug HexaDecimalToDecimal("$1A0f")
Debug HexaDecimalToDecimal("10")
Debug HexaDecimalToDecimal("$1u0")
Debug HexaDecimalToDecimal("$ABCDEF")
Debug HexaDecimalToDecimal("$abcdef")
Debug HexaDecimalToDecimal("$12345678")
Debug HexaDecimalToDecimal("$123456781")
Eric,
j'ai légèrement modifié ton code et l'amélioration sur ma bécanne est de 1 % pour 500000 itérations pour une chaine hexa de 8 caractères et de moins de 2 % pour une chaine de 1 caractère , c'est faible.
j'ai légèrement modifié ton code et l'amélioration sur ma bécanne est de 1 % pour 500000 itérations pour une chaine hexa de 8 caractères et de moins de 2 % pour une chaine de 1 caractère , c'est faible.
Code : Tout sélectionner
Procedure ValHex1(Chaine.s)
Valeur.l
MOV ecx,Chaine
CMP byte [ecx],'$'
JNZ NonChaineHexa1
!LEA ebx,[TableValeur1]
MOV edx,0
XOR eax,eax
!Encore1:
INC ecx
MOV al,byte [ecx]
CMP al,0
JE FinChaineHexa1
XLATB
ADD edx, edx ; ajouté ça, edx = edx * 2
CMP al,$FF
JE NonChaineHexa1
LEA edx, [(edx*8)+eax] ; ajouté ça, opération effectuée en 1 cycle d'horloge sur les pentium double pipeline
; ROL edx,4
; ADD edx,eax
JMP Encore1
!FinChaineHexa1:
MOV Valeur,edx
ProcedureReturn Valeur
!NonChaineHexa1:
ProcedureReturn 0
!TableValeur1:
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $00,$01,$02,$03,$04,$05,$06,$07,$08,$09,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$0A,$0B,$0C,$0D,$0E,$0F,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$0A,$0B,$0C,$0D,$0E,$0F,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
EndProcedure
Voilà pour le soldat inconnu, la fonction binaire en décimal sur 32 bits
2 versions, la première ne controle pas la longueur de la chaine, la seconde oui et retoure 0 si la chaine a plus de 32 caractères binaires (hormis le %) ou si la chaine en 0 (hormis le %)
le second
2 versions, la première ne controle pas la longueur de la chaine, la seconde oui et retoure 0 si la chaine a plus de 32 caractères binaires (hormis le %) ou si la chaine en 0 (hormis le %)
Code : Tout sélectionner
Procedure.l BinaireToDecimal(Chaine.s)
; calcul de la valeur décimale d'une chaîne bianaire sur 32 bits
; le principe est celui des additions successives des valeurs de chaque caractère binaire
; en fonction de sa position dans la chaîne
; par exemple le nombre hexa %10 vaut en décimal 2
; La décomposition de %10 est
; 1 : 1 * 2^1 = 1 * 2 = 2
; 0 : 0 * 2^0 = 0 * 1 = 0
; Total : 2 + 0 = 2
;
; Le principe est de multipier le résultat précédant par 2 et d'ajouter 0 ou 1 en fonction du
; caractère binaire. Il est plus rapide de ne pas faire de test et d'ajouter la valeur même
; si cette valeur vaut 0
; La chaîne binaire mesure sans le $ a au max 32 caractères
; eax stocke le résultat
; ebx contient l'adresse de la chaine binaire
; edx reçoit les caractères de la chaine pour les tests
; le code ne contrôle pas le nombre de caractères de la chaîne
MOV ebx,Chaine
CMP byte [ebx],'%'
JNZ NonChaineBinaire
XOR eax, eax
!DebutCalcul:
INC ebx ; incrémentation de l'adresse de la chaine
MOVZX edx, byte [ebx] ; dl = le caractère binaire pointé par ebx
TEST dl, dl ; si = 0 on quitte, fin de chaine
JZ FinchaineBinaire
ADD dl, -'0' ; soustrait la valeur ASCII du 0
JS NonChaineBinaire ; erreur si nombre négatif
CMP dl, 1
JA NonChaineBinaire ; erreur si > 1
LEA eax, [eax*2+edx] ; multiplication de eax par 2 puis ajout de edx, résultat
; dans eax
JMP DebutCalcul ; on reboucle
!NonChaineBinaire:
MOV eax, 0
!FinchaineBinaire:
ProcedureReturn
EndProcedure
le second
Code : Tout sélectionner
Procedure.l BinaireToDecimal(Chaine.s)
MOV ebx,Chaine
CMP byte [ebx],'%'
JNZ NonChaineBinaire
PUSH ebx
SUB eax, eax ; eax = 0
; calcul de la longueur de la chaine
!Compte:
INC ebx ; on passe le %
MOV dl, [ebx]
TEST dl, dl
JZ FinComptage
INC eax
JMP Compte
!FinComptage:
POP ebx
CMP eax, 32
JA NonChaineBinaire ; on quitte si la chaine > 32 caractères
TEST eax, eax
JZ NonChaineBinaire ; on quitte si la chaine = 0 caractère
XOR eax, eax
!DebutCalcul:
INC ebx ; incrémentation de l'adresse de la chaine
MOVZX edx, byte [ebx] ; dl = le caractère binaire pointé par ebx
TEST dl, dl ; si = 0 on quitte, fin de chaine
JZ FinchaineBinaire
ADD dl, -'0' ; soustrait la valeur ASCII du 0
JS NonChaineBinaire ; erreur si nombre négatif
CMP dl, 1
JA NonChaineBinaire ; erreur si > 1
LEA eax, [eax*2+edx] ; multiplication de eax par 2 puis ajout de edx, résultat
; dans eax
JMP DebutCalcul ; on reboucle
!NonChaineBinaire:
MOV eax, 0
!FinchaineBinaire:
ProcedureReturn
EndProcedure
J'ai plusieurs livres sur l'asm ou certaines instructions sont parfois commentées pour l'optimisation. Pour LEA, 1 cycle est vrai si l'instruction précédante n'a pas pas modifié un des registres utilisé, sinon l'instruction prend 2 cycles.erix14 a écrit :Salut Denis,Tu as de la documentation sur les cycles d'horloge des Pentium ?ajouté ça, opération effectuée en 1 cycle d'horloge sur les pentium double pipeline
Moi, j'ai maximum celui du 486. Et j'ai cherché sur Internet, mais n'est encore rien trouvé.
Il me semble avoir lu qu'il a de la doc MS avec les cycles d'instruction, mais je n'en sait pas plus.
Il y a de la doc Intel sur l'optimisation mais je n'ai pas détaillé (en anglais)
La page Intel
http://developer.intel.com/design/penti ... ex_new.htm
-
- Messages : 4312
- Inscription : mer. 28/janv./2004 20:58
- Localisation : Clermont ferrand OU Olsztyn
- Contact :
j'ai supprimé la vérif du $ au début
et j'ai fait de même pour le binaire car ma sltuion visiblement plus simple est finallement pus lente (commparé avec les carac 0 et 1, sion erreur)
Code : Tout sélectionner
Procedure HexVal(Hex.s)
Protected Val.l
MOV ecx, Hex
LEA ebx, [TableValeurHex]
MOV edx, 0
MOV eax, 0
! EncoreChaineHex :
MOV al, byte[ecx]
CMP al, 0
JE FinChaineHex
XLATB
CMP eax, $FF
JE ErreurChaineHex
ROL edx, 4
ADD edx, eax
INC ecx
JMP EncoreChaineHex
! FinChaineHex :
MOV Val, edx
ProcedureReturn Val
! ErreurChaineHex :
ProcedureReturn -1
! TableValeurHex :
! DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
! DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
! DB $FF, $FF, $FF, $FF, $00, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
! DB $00, $01, $02, $03, $04, $05, $06, $07, $08, $09, $FF, $FF, $FF, $FF, $FF, $FF
! DB $FF, $0A, $0B, $0C, $0D, $0E, $0F, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
! DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
! DB $FF, $0A, $0B, $0C, $0D, $0E, $0F, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
! DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
! DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
! DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
! DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
! DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
! DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
! DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
! DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
! DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
EndProcedure
Code : Tout sélectionner
Procedure BinVal2(Bin.s)
Protected Val.l
MOV ecx, Bin
LEA ebx, [TableValeurBin]
MOV edx, 0
MOV eax, 0
! EncoreChaineBin :
MOV al, byte[ecx]
CMP al, 0
JE FinChaineBin
XLATB
CMP eax, $FF
JE ErreurChaineBin
ROL edx, 1
ADD edx, eax
INC ecx
JMP EncoreChaineBin
! FinChaineBin :
MOV Val, edx
ProcedureReturn Val
! ErreurChaineBin :
ProcedureReturn -1
! TableValeurBin :
! DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
! DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
! DB $FF, $FF, $FF, $FF, $FF, $00, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
! DB $00, $01, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
! DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
! DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
! DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
! DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
! DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
! DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
! DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
! DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
! DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
! DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
! DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
! DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
EndProcedure
Dernière modification par Le Soldat Inconnu le sam. 19/mars/2005 19:15, modifié 1 fois.
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?
[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Et le cahier des charges ?Le Soldat Inconnu a écrit :j'ai supprimé la vérif du $ au début
Code : Tout sélectionner
Procedure HexVal(Hex.s) Protected Val.l MOV ecx, Hex LEA ebx, [TableValeurHex] MOV edx, 0 MOV eax, 0 ! EncoreChaineHex : MOV al, byte[ecx] CMP al, 0 JE FinChaineHex XLATB CMP eax, $FF JE ErreurChaineHex ROL edx, 4 ADD edx, eax INC ecx JMP EncoreChaineHex ! FinChaineHex : MOV Val, edx ProcedureReturn Val ! ErreurChaineHex : ProcedureReturn -1 ! TableValeurHex : ! DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF ! DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF ! DB $FF, $FF, $FF, $FF, $00, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF ! DB $00, $01, $02, $03, $04, $05, $06, $07, $08, $09, $FF, $FF, $FF, $FF, $FF, $FF ! DB $FF, $0A, $0B, $0C, $0D, $0E, $0F, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF ! DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF ! DB $FF, $0A, $0B, $0C, $0D, $0E, $0F, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF ! DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF ! DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF ! DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF ! DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF ! DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF ! DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF ! DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF ! DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF ! DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF EndProcedure
-
- Messages : 4312
- Inscription : mer. 28/janv./2004 20:58
- Localisation : Clermont ferrand OU Olsztyn
- Contact :
Denis, dis-moi si tu obtiens ( avec le code ci-dessous )
60 cycles d'horloge pour le code 1
et 52 cycle d'horloge pour le code 2
ce qui correspond à 6 cycles d'horloge pour et 5,2 pour
Ce qui voudrait dire que LEA... ne fait pas 1 cycle d'horloge...
60 cycles d'horloge pour le code 1
et 52 cycle d'horloge pour le code 2
Code : Tout sélectionner
Structure LL
Low.l
High.l
EndStructure
Global Debut.LL,Fin.LL,CyclesHorlogeAVide.l,CyclesHorloge1.l,CyclesHorloge2.l,CyclesHorlogeTemp.l
CyclesHorlogeAVide = 999999999
CyclesHorloge1 = 999999999
CyclesHorloge2 = 999999999
MOV ecx,100000
!EncoreCycles:
!RDTSC
MOV Debut\Low, eax
MOV Debut\High, edx
!RDTSC
MOV Fin\Low, eax
MOV Fin\High, edx
!fild qword [v_Fin]
!fild qword [v_Debut]
!fsubp
!fistp dword[v_CyclesHorlogeTemp]
If CyclesHorlogeTemp < CyclesHorlogeAVide
CyclesHorlogeAVide = CyclesHorlogeTemp
EndIf
!RDTSC
MOV Debut\Low, eax
MOV Debut\High, edx
;/ code 1
ROL edx,4
ADD edx,eax
ROL edx,4
ADD edx,eax
ROL edx,4
ADD edx,eax
ROL edx,4
ADD edx,eax
ROL edx,4
ADD edx,eax
ROL edx,4
ADD edx,eax
ROL edx,4
ADD edx,eax
ROL edx,4
ADD edx,eax
ROL edx,4
ADD edx,eax
ROL edx,4
ADD edx,eax
;/ fin code 1
!RDTSC
MOV Fin\Low, eax
MOV Fin\High, edx
!fild qword [v_Fin]
!fild qword [v_Debut]
!fsubp
!fistp dword[v_CyclesHorlogeTemp]
If CyclesHorlogeTemp < CyclesHorloge1
CyclesHorloge1 = CyclesHorlogeTemp
EndIf
!RDTSC
MOV Debut\Low, eax
MOV Debut\High, edx
;/ code 2
ADD edx, edx
LEA edx, [(edx*8)+eax]
ADD edx, edx
LEA edx, [(edx*8)+eax]
ADD edx, edx
LEA edx, [(edx*8)+eax]
ADD edx, edx
LEA edx, [(edx*8)+eax]
ADD edx, edx
LEA edx, [(edx*8)+eax]
ADD edx, edx
LEA edx, [(edx*8)+eax]
ADD edx, edx
LEA edx, [(edx*8)+eax]
ADD edx, edx
LEA edx, [(edx*8)+eax]
ADD edx, edx
LEA edx, [(edx*8)+eax]
ADD edx, edx
LEA edx, [(edx*8)+eax]
;/ fin code 2
!RDTSC
MOV Fin\Low, eax
MOV Fin\High, edx
!fild qword [v_Fin]
!fild qword [v_Debut]
!fsubp
!fistp dword[v_CyclesHorlogeTemp]
If CyclesHorlogeTemp < CyclesHorloge2
CyclesHorloge2 = CyclesHorlogeTemp
EndIf
DEC ecx
JNZ EncoreCycles
message$ = "Cycles d'horloge code 1 : " + Str(CyclesHorloge1-CyclesHorlogeAVide) + Space(20) + Chr(13)
message$ = message$ + "Cycles d'horloge code 2 : " + Str(CyclesHorloge2-CyclesHorlogeAVide) + Chr(13)
MessageRequester("Vitesse ASM", message$, #MB_ICONINFORMATION)
Code : Tout sélectionner
ROL edx,4
ADD edx,eax
Code : Tout sélectionner
ADD edx, edx
LEA edx, [(edx*8)+eax]
Eric,
j'ai lancé ton code et j'ai la même valeur pour les 2 codes, 2280.
J'ai regardé à nouveau dans le bouquin de Michael Abrash, édition sybex, : Programmation graphique C/C++ Assembleur.
Pour LEA, sur pentium, mais pour d'autre instructions également, il y a les verrouillages du pipeline (AGI = Adress generation Interlock) qui peuvent ralentir les instructions.
Voici ce que dit le bouquin sur la règle de l'AGI
Si on modifie n'importe quelle partie d'un registre pendant un cycle, on ne peut pas utiliser ce registre pour adresser la mémoire pendant ce cycle ou le cycle suivant. (1 instruction est effectuée dans le pipeline U et l'instruction suivante est effectuée dans le pipeline V pendant le même cycle d'horloge et prend donc 1 cycle si la règle de l'AGI est respectée).
Si on effectue le code suivant, on perd 1 cycle d'établissement dans les pipelines)
C'est pour ça que dans ton code que j'ai modifié j'ai placé le ADD edx, edx bien avant le LEA
Voici le code que j'ai utilisé pour comparer les vitesse sur celeron 2 Go.
J'ai refait des tests et je me suis rendu compte que je n'avais pas désactivé le débugger
Sans le débugger, le code avec le ROL est légèrement plus rapide pour une chaine courte et légèrement plus long pour une chaine longue, le tout pour moins de 1 %.
Le debugger a vraiment une grosse influence sur les tests.
j'ai lancé ton code et j'ai la même valeur pour les 2 codes, 2280.
J'ai regardé à nouveau dans le bouquin de Michael Abrash, édition sybex, : Programmation graphique C/C++ Assembleur.
Pour LEA, sur pentium, mais pour d'autre instructions également, il y a les verrouillages du pipeline (AGI = Adress generation Interlock) qui peuvent ralentir les instructions.
Voici ce que dit le bouquin sur la règle de l'AGI
Si on modifie n'importe quelle partie d'un registre pendant un cycle, on ne peut pas utiliser ce registre pour adresser la mémoire pendant ce cycle ou le cycle suivant. (1 instruction est effectuée dans le pipeline U et l'instruction suivante est effectuée dans le pipeline V pendant le même cycle d'horloge et prend donc 1 cycle si la règle de l'AGI est respectée).
Si on effectue le code suivant, on perd 1 cycle d'établissement dans les pipelines)
Code : Tout sélectionner
ADD edx, edx
LEA edx, [(edx*8)+eax]
Voici le code que j'ai utilisé pour comparer les vitesse sur celeron 2 Go.
J'ai refait des tests et je me suis rendu compte que je n'avais pas désactivé le débugger
Sans le débugger, le code avec le ROL est légèrement plus rapide pour une chaine courte et légèrement plus long pour une chaine longue, le tout pour moins de 1 %.
Le debugger a vraiment une grosse influence sur les tests.
Code : Tout sélectionner
Procedure ValHex(Chaine.s)
Valeur.l
MOV ecx,Chaine
CMP byte [ecx],'$'
JNZ NonChaineHexa
!LEA ebx,[TableValeur]
MOV edx,0
XOR eax,eax
!Encore:
INC ecx
MOV al,byte [ecx]
CMP al,0
JE FinChaineHexa
XLATB
CMP al,$FF
JE NonChaineHexa
ROL edx,4
ADD edx,eax
JMP Encore
!FinChaineHexa:
MOV Valeur,edx
ProcedureReturn Valeur
!NonChaineHexa:
ProcedureReturn 0
!TableValeur:
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $00,$01,$02,$03,$04,$05,$06,$07,$08,$09,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$0A,$0B,$0C,$0D,$0E,$0F,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$0A,$0B,$0C,$0D,$0E,$0F,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
EndProcedure
;
Procedure ValHex1(Chaine.s)
Valeur.l
MOV ecx,Chaine
CMP byte [ecx],'$'
JNZ NonChaineHexa1
!LEA ebx,[TableValeur1]
MOV edx,0
XOR eax,eax
!Encore1:
INC ecx
MOV al,byte [ecx]
CMP al,0
JE FinChaineHexa1
XLATB
ADD edx, edx
CMP al,$FF
JE NonChaineHexa1
LEA edx, [edx*8+eax]
; ROL edx,4
; ADD edx,eax
JMP Encore
!FinChaineHexa1:
MOV Valeur,edx
ProcedureReturn Valeur
!NonChaineHexa1:
ProcedureReturn 0
!TableValeur1:
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $00,$01,$02,$03,$04,$05,$06,$07,$08,$09,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$0A,$0B,$0C,$0D,$0E,$0F,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$0A,$0B,$0C,$0D,$0E,$0F,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
! DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
EndProcedure
SetPriorityClass_(GetCurrentProcess_(),#HIGH_PRIORITY_CLASS )
Temps1 = ElapsedMilliseconds()
For i = 1 To 50000000
ValHex("$A0")
Next i
Temps2 = ElapsedMilliseconds()
For i = 1 To 50000000
ValHex1("$A0")
Next i
Temps3 = ElapsedMilliseconds()
SetPriorityClass_(GetCurrentProcess_(),#NORMAL_PRIORITY_CLASS)
MessageRequester("Test rapidité", "Solution 1 : " + Str(Temps2 - Temps1) + " ; Solution 2 : " + Str(Temps3 - Temps2) + Chr(10) + "Ratio = 1 / " + StrF((Temps2 - Temps1) / (Temps3 - Temps2)), 0)
SetPriorityClass_(GetCurrentProcess_(),#HIGH_PRIORITY_CLASS )
Temps1 = ElapsedMilliseconds()
For i = 1 To 5000000
ValHex("$ABCDEF19")
Next i
Temps2 = ElapsedMilliseconds()
For i = 1 To 5000000
ValHex1("$ABCDEF19")
Next i
Temps3 = ElapsedMilliseconds()
SetPriorityClass_(GetCurrentProcess_(),#NORMAL_PRIORITY_CLASS)
MessageRequester("Test rapidité", "Solution 1 : " + Str(Temps2 - Temps1) + " ; Solution 2 : " + Str(Temps3 - Temps2) + Chr(10) + "Ratio = 1 / " + StrF((Temps2 - Temps1) / (Temps3 - Temps2)), 0)