Je déterre ce post de 2005 car depuis il y a eu des améliorations.
Tout d’abord merci aux anciens qui ne viennent plus très souvent sur le forum Erix14 Denis et aux deux autres encore là djes et LSI
Dans un premier temps je me suis limité aux conversions sur un octet pour deux raisons.
La première raison est donnée par les tests qui suivent.
La deuxième est purement logique.
En effet lorsque l’on dumpe une mémoire ou un fichier il est assez rare que l’on connaisse parfaitement la structure de la zone dumpée. Or intel code ses nombres en little indian.
Ce qui ne correspond pas à l’ordre croissant des poids des nombres et des adresses croissantes.
L’argument principal de ce post vient des tests effectués aujourd’hui et qui confirme 2 méthodes beaucoup plus rapides que les 2 prg ASM
Pour le fun j’ai codé moi-même un PRG en ASM, mais s’il est un peu plus rapide que ceux de 2005 il est loin de concurrencer les 2 autres méthodes
Code : Tout sélectionner
Structure EL_h
Bn.s{8}
Hx.s{2}
StructureUnion
VA.a ; ascii
VB.b ; byte
VC.c ; character
VS.s{1}; String 1 Byte
EndStructureUnion
EndStructure
Structure tab_H
Array el.el_H(256)
EndStructure
Global NewMap mp256.EL_H()
Global NewMap mp256b.EL_H() ; Pour obtenir des temps inférieures à la méthode classique val($xx) la map des binaires a été sortie
Global TAB.tab_h
ProcedureDLL.q __nbcs() ;**** Procédure pour évaluer le nb de cycles machine
!RDTSC
ProcedureReturn
EndProcedure
Procedure ValHex(Chaine.s) ;de Erix14 Denis LSI
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) ;de Erix14 Denis LSI
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
Procedure.a CONV_HEX_CODM(HEX1.s) ;***** ici on passe la valeur de l'octet ******
; p.v_HEX1 equ esp+PS0+0 si HEX1
; p.p_HEX1 equ esp+PS0+0 si *HEX1
; p.v_VL equ esp+0
Protected VL.a
!LEA ebx,[P_Tab_Val_b] ; Charge l'adresse de la table de conversion necessaire à l'instruction XLATB
!xor edx,edx ; 0 dans EAX
!MOV ebp,dword [p.v_HEX1]
!MOVZX eax,byte [ebp+1] ; Charge bit de plus fort poids
!sub al,$30 ; Soutraire $30 ou 48 decimal pour obtenir l'offset de la table de conversion
!XLATB ; Remplace la valeur de AL offset pour la table par la valeur trouvée dans la table adresse en EBX résultat dans AL
!MOV DL,al ; Sauvegarde de AL dans DL partie Basse de DX
!MOVZX eax,byte [ebp] ; Charge bit de plus faible poids
!sub al,$30 ; Soutraire $30 ou 48 decimal pour obtenir l'offset de la table de conversion
!XLATB ; Remplace la valeur de AL offset pour la table par la valeur trouvée dans la table adresse en EBX résultat dans AL
!SHL AX,4 ; décalage vers la gauche de 4 bits donc multiplication par 16
!add dx,ax ;:Addition du poids faible et du poids fort dans DX
!MOV [p.v_VL],dx ; Passage de la valeur Bin dans VL et passage en retour de PRG
ProcedureReturn VL
!P_Tab_Val_b: ;; Table de conversion d'Hexa en Binaire ou code machine
! DB $00,$01,$02,$03,$04,$05,$06,$07,$08,$09,$FF,7 dup $FF,$0A,$0B,$0C,$0D,$0E,$0F, 240 dup ($FF)
EndProcedure
Procedure.l CHARG_TAB_MAP(FL.b)
; si FL=1 chargement de la table seule si FL= 2 chargement de la map mp256 (hex) si FL =4 chargement de la map mp256p (bin)
; si F1 = 3 chargement de la table et de la map mp256 seulemet si FL=5 charment de la Table et de la map mp256b (bin)
; si FL=6 chargement de map256 (hex) et de la map mp256p (bin) si FL=7 chargement de la table et des deux MAp
Static flag.b=0; ,*adrs.S_x_cr,*sort.S_x_cr
Protected _ii.i;,typ${1}="",rmp${1}="",pref${1}="",ret_xx.s="",
If flag=0 ; passe ici une seule fois au premier appel
; ** Chargement de la table en accés direct
For _ii=0 To 255
If Fl= 1 Or 3 Or 5 Or 7 ; chargement de table acces direct
tab\el(_ii)\bn=RSet(Bin(_ii,#PB_Ascii),8,"0")
tab\el(_ii)\Hx=RSet(Hex(_ii,#PB_Ascii),2,"0")
; tab\el(_ii)\Hx=CONV_DEC_HEX(_ii) ; Utilisable si CONV_DEC_HEX() est présent plus rapide que hex()
; tab\el(_ii)\VA=_ii
;**** Essai d'utilisation d'une map pour convertir bin en Hexa ou en bin expensé moins rapide que la table à accés direct ******
; AddMapElement(mp256(),Chr(_ii))
; mp256()\Bn=tab\el(_ii)\bn
; mp256()\Hx=tab\el(_ii)\Hx
; mp256()\VA=_ii
EndIf
If FL=2 Or 4
AddMapElement(mp256(),RSet(Hex(_ii,#PB_Ascii),2,"0"))
mp256()\Bn=RSet(Bin(_ii,#PB_Ascii),8,"0")
mp256()\Hx=RSet(Hex(_ii,#PB_Ascii),2,"0")
mp256()\VA=_ii
EndIf
If FL=3 Or 7
AddMapElement(mp256(),tab\el(_ii)\Hx)
mp256()\Bn=tab\el(_ii)\bn
mp256()\Hx=tab\el(_ii)\Hx
mp256()\VA=_ii
EndIf
If Fl>3
AddMapElement(mp256b(),tab\el(_ii)\bn)
mp256b()\Bn=tab\el(_ii)\bn
mp256b()\Hx=tab\el(_ii)\Hx
mp256b()\VA=_ii
EndIf
Next
EndIf
flag+1 ; pour compter le nb d'appels inutils
EndProcedure
; Vq.q=$123456789012345
; H$=Hex(Vq)
; VALh.q=Valhex("$"+H$)
; Debug vq-VALh ;; ICI ERREUR LES 2 PRG NE DECODENT QUE SUR 4 OCTETS MAX
; Vq.q=$12345678
; H$=Hex(Vq)
; VALh.q=Valhex("$"+H$)
; Debug vq-VALh
;
; End
; charg_tab_map(3)
; For i=0 To $FF
; A$=RSet(Hex(i),2,"0")
; FindMapElement(Mp256(),A$)
; val00=mp256()\VA
; Debug _n(val00)+_n(I)+_s(A$)
; Next
; For i=0 To 255
; A$=RSet(Hex(i),2,"0")
; val0=Val("$"+A$)
; Debug _n(val0)+_n(I)+_s(A$)
; Next
; For i=0 To 255
; A$=RSet(Hex(i),2,"0")
; val=ValHEX("$"+A$)
; Debug _n(val)+_n(I)+_s(A$)
; Next
; For i=0 To 255
; A$=RSet(Hex(i),2,"0")
; Debug _n(CONV_HEX_CODM(A$))+_n(I)+_s(A$)
; Next
; End
;*************************************************************************************************
resultat$=""
SetPriorityClass_(GetCurrentProcess_(),#HIGH_PRIORITY_CLASS)
BMAX=20000
Hmin=0
Hmax=$FF ; Vous pouvez tester les prg sur 4 octets mais 2 methodes ne sont codées que sur un octet
RESULTAT$+" CONDITIONS ==>: BMAX="+Str(BMAX)+" Hmin="+Str(Hmin)+" Hmax="+Str(Hmax)+#CRLF$
D1.q=__nbcs()
De1=ElapsedMilliseconds()
charg_tab_map(3)
resultat$+"Chargement de la table:"+Str(__nbcs()-D1)+#CRLF$+"Temps elapse ="+Str(ElapsedMilliseconds()-De1)+#CRLF$
DUR0.q=ElapsedMilliseconds()-De1
D1.q=__nbcs()
De1=ElapsedMilliseconds()
For j=0 To BMAX
For i=hmin To Hmax
A$=RSet(Hex(i),4,"0")
val.a=Val("$"+A$)
Next
Next
resultat$+"val=Val('$'+A$):"+Str(__nbcs()-D1)+#CRLF$+"Temps elapse ="+Str(ElapsedMilliseconds()-De1)+#CRLF$
DUR1.q=ElapsedMilliseconds()-De1
D1.q=__nbcs()
De1=ElapsedMilliseconds()
For j=0 To BMAX
For i=hmin To Hmax
A$=RSet(Hex(i),4,"0")
val.a=ValHEX("$"+A$)
Next
Next
resultat$+"ValHEX('$'+A$):"+Str(__nbcs()-D1)+#CRLF$+"Temps elapse ="+Str(ElapsedMilliseconds()-De1)+#CRLF$
DUR2.q=ElapsedMilliseconds()-De1
D1.q=__nbcs()
De1=ElapsedMilliseconds()
For j=0 To BMAX
For i=hmin To Hmax
A$=RSet(Hex(i),4,"0")
val.a=ValHEX1("$"+A$)
Next
Next
resultat$+"ValHEX1('$'+A$):"+Str(__nbcs()-D1)+#CRLF$+"Temps elapse ="+Str(ElapsedMilliseconds()-De1)+#CRLF$
DUR3.q=ElapsedMilliseconds()-De1
D1.q=__nbcs()
De1=ElapsedMilliseconds()
For j=0 To BMAX
For i=hmin To Hmax
A$=RSet(Hex(i),2,"0")
val.a=CONV_HEX_CODM(A$)
Next
Next
resultat$+"CONV_HEX_CODM(A$):"+Str(__nbcs()-D1)+#CRLF$+"Temps elapse ="+Str(ElapsedMilliseconds()-De1)+#CRLF$
DUR4.q=ElapsedMilliseconds()-De1
D1.q=__nbcs()
De1=ElapsedMilliseconds()
For j=0 To BMAX
For i=hmin To Hmax
A$=RSet(Hex(i),2,"0")
FindMapElement(Mp256(),A$)
val.a=mp256()\VA
Next
Next
resultat$+"FindMapElement(Mp256(),A$):"+Str(__nbcs()-D1)+#CRLF$+"Temps elapse ="+Str(ElapsedMilliseconds()-De1)+#CRLF$
DUR5.q=ElapsedMilliseconds()-De1
D1.q=__nbcs()
De1=ElapsedMilliseconds()
For j=0 To BMAX
For i=hmin To Hmax
A$=RSet(Hex(i),2,"0")
; RIEN afin de décompter le temps de la boucle et de ne garder que le temps des instructions utiles
Next
Next
resultat$+"sans rien:"+Str(__nbcs()-D1)+#CRLF$+Str(ElapsedMilliseconds()-De1)+#CRLF$
DURdur.q=ElapsedMilliseconds()-De1
resultat$+" Temps réel de val()="+Str(DUR1-DURDUR)+#CRLF$
resultat$+" Temps réel de VALHEX()="+Str(DUR2-DURDUR)+#CRLF$
resultat$+" Temps réel de VALHEX1()="+Str(DUR3-DURDUR)+#CRLF$
resultat$+" Temps réel de CONV_HEX_CODM="+Str(DUR4-DURDUR)+#CRLF$
resultat$+" Temps réel de FindMapElement(Mp256()="+Str(DUR5-DURDUR)+#CRLF$
MessageRequester("ATTENTION",resultat$)
CreateFile(00,"C:\RESUL_conv_hex_bin.txt")
WriteData(00,@resultat$,Len(resultat$))
CloseFile(00)
Un fichier "C:\RESUL_conv_hex_bin.txt" vous donne les résultats en txt ,ils peuvent être donné ici
Les 2 programmes valhex() et valhex1() ne convertissent que les type .l 4 octets mais pas les types .q 8 octets non connus en 2005 dans PB (Voir tests en commentaire)
1) l'instruction VAL() est nettement plus rapide que les programmes ASM et donne la possibilité de convertir jusqu'à 8 octets type .q
2) la méthode d'une table exploitée avec map() est la solution la plus rapide.
Pouvez vous me confirmer les résultats obtenus ici merci d'avance.