Page 1 sur 2
Conversion d'octets signés en non signés
Publié : sam. 21/mai/2005 22:44
par Droopy
Quand j'utilise des fonctions logiques ( XOR / AND / OR ) sur des variables de type Byte, vu que PureBasic considère celles ci comme des variables signées, le résultat n'est pas facilement lisible .
Bref voici comment les convertir en non signés
Code : Tout sélectionner
Procedure SignedBinaryToUnsigned(Byte.b)
If Byte & %10000000
Byte=Byte & %01111111
Retour=Byte+128
Else
Retour=Byte
EndIf
ProcedureReturn Retour
EndProcedure
A tester avec ceci :
Code : Tout sélectionner
;/ Unsigned Signed
Debug SignedBinaryToUnsigned(%00000000) ; 0 0
Debug SignedBinaryToUnsigned(%01111111) ; 127 127
Debug SignedBinaryToUnsigned(%10000000) ; 128 -128
Debug SignedBinaryToUnsigned(%11111111) ; 255 -1
Publié : dim. 22/mai/2005 0:10
par erix14
J'ai plus simple
Code : Tout sélectionner
Procedure SignedBinaryToUnsigned(Byte.b)
!MOV dword [esp+1],eax
ProcedureReturn Retour
EndProcedure
;/ Unsigned Signed
Debug SignedBinaryToUnsigned(%00000000) ; 0 0
Debug SignedBinaryToUnsigned(%01111111) ; 127 127
Debug SignedBinaryToUnsigned(%10000000) ; 128 -128
Debug SignedBinaryToUnsigned(%11111111) ; 255 -1
Publié : dim. 22/mai/2005 6:05
par Anonyme2
Y a plus simple en PB (même si ça ne saute pas au yeux), voir le message de Fred sur le forum anglais en 2003
http://forums.purebasic.com/english/vie ... ght=signed
Publié : dim. 22/mai/2005 7:10
par Droopy
Merci Erix14 et Denis pour vos réponses
Il y avait effectivement plus simple
Je dois dire que le code assembleur me laisse perplexe !
Code : Tout sélectionner
Procedure SignedBinaryToUnsigned(Byte.b)
retour=Byte
If retour < 0
retour + 256
EndIf
ProcedureReturn retour
EndProcedure
;/ Unsigned Signed
Debug SignedBinaryToUnsigned(%00000000) ; 0 0
Debug SignedBinaryToUnsigned(%01111111) ; 127 127
Debug SignedBinaryToUnsigned(%10000000) ; 128 -128
Debug SignedBinaryToUnsigned(%11111111) ; 255 -1
Publié : dim. 22/mai/2005 7:15
par Droopy
Après relecture du forum US il y a encore plus simple
Code : Tout sélectionner
Procedure SignedBinaryToUnsigned(Byte.b)
retour=Byte & $FF
ProcedureReturn retour
EndProcedure
Code de Fred
Publié : dim. 22/mai/2005 7:27
par Anonyme2
Droopy a écrit :Après relecture du forum US il y a encore plus simple
Code : Tout sélectionner
Procedure SignedBinaryToUnsigned(Byte.b)
retour=Byte & $FF
ProcedureReturn retour
EndProcedure
Code de Fred
Plus simple
Code : Tout sélectionner
Procedure SignedBinaryToUnsigned(Byte.b)
ProcedureReturn Byte & $FF
EndProcedure
Publié : dim. 22/mai/2005 7:43
par erix14
Bravo Denis, du remporte le premier prix de la catégorie procédure
Code : Tout sélectionner
Global Time1,Time2
Global a.b,b.l
Procedure SignedBinaryToUnsigned(byte.b)
If byte & %10000000
byte=byte & %01111111
Retour=byte+128
Else
Retour=byte
EndIf
ProcedureReturn Retour
EndProcedure
Procedure SignedBinaryToUnsignedASM(byte.b)
!MOV dword [esp+1],eax
ProcedureReturn Retour
EndProcedure
Procedure SignedBinaryToUnsignedDenis(byte.b)
ProcedureReturn byte & $FF
EndProcedure
Procedure SignedBinaryToUnsignedFred(byte.b)
Retour=byte & $FF
ProcedureReturn Retour
EndProcedure
If OpenWindow(1,200,200,350,200,#PB_Window_SystemMenu,"Programme de test")
Time1.l = GetTickCount_()
For t=1 To 10000000
;/ Unsigned Signed
b = SignedBinaryToUnsigned(%00000000) ; 0 0
b = SignedBinaryToUnsigned(%01111111) ; 127 127
b = SignedBinaryToUnsigned(%10000000) ; 128 -128
b = SignedBinaryToUnsigned(%11111111) ; 255 -1
Next
Time2.l = GetTickCount_()
StartDrawing(WindowOutput())
FrontColor(0,0,0)
DrawingMode(1)
Locate(20,10):DrawText("Durée Procedure Droopy (en ms) :")
Locate(280,10):DrawText(Str(Time2-Time1))
StopDrawing()
Time1.l = GetTickCount_()
For t=1 To 10000000
;/ Unsigned Signed
b = SignedBinaryToUnsignedASM(%00000000) ; 0 0
b = SignedBinaryToUnsignedASM(%01111111) ; 127 127
b = SignedBinaryToUnsignedASM(%10000000) ; 128 -128
b = SignedBinaryToUnsignedASM(%11111111) ; 255 -1
Next
Time2.l = GetTickCount_()
StartDrawing(WindowOutput())
FrontColor(0,0,0)
DrawingMode(1)
Locate(20,40):DrawText("Durée Procedure ASM (en ms) :")
Locate(280,40):DrawText(Str(Time2-Time1))
StopDrawing()
Time1.l = GetTickCount_()
For t=1 To 10000000
;/ Unsigned Signed
b = SignedBinaryToUnsignedDenis(%00000000) ; 0 0
b = SignedBinaryToUnsignedDenis(%01111111) ; 127 127
b = SignedBinaryToUnsignedDenis(%10000000) ; 128 -128
b = SignedBinaryToUnsignedDenis(%11111111) ; 255 -1
Next
Time2.l = GetTickCount_()
StartDrawing(WindowOutput())
FrontColor(0,0,0)
DrawingMode(1)
Locate(20,70):DrawText("Durée Procedure Denis (en ms) :")
Locate(280,70):DrawText(Str(Time2-Time1))
StopDrawing()
Time1.l = GetTickCount_()
For t=1 To 10000000
;/ Unsigned Signed
b = SignedBinaryToUnsignedFred(%00000000) ; 0 0
b = SignedBinaryToUnsignedFred(%01111111) ; 127 127
b = SignedBinaryToUnsignedFred(%10000000) ; 128 -128
b = SignedBinaryToUnsignedFred(%11111111) ; 255 -1
Next
Time2.l = GetTickCount_()
StartDrawing(WindowOutput())
FrontColor(0,0,0)
DrawingMode(1)
Locate(20,100):DrawText("Durée Procedure Fred (en ms) :")
Locate(280,100):DrawText(Str(Time2-Time1))
StopDrawing()
Time1.l = GetTickCount_()
For t=1 To 10000000
;/ Unsigned Signed
a = %00000000
b = a & $FF ; 0 0
a = %01111111
b = a & $FF ; 127 127
a = %10000000
b = a & $FF ; 128 -128
a = %11111111
b = a & $FF ; 255 -1
Next
Time2.l = GetTickCount_()
StartDrawing(WindowOutput())
FrontColor(0,0,0)
DrawingMode(1)
Locate(20,130):DrawText("Durée direct en PureBasic (en ms) :")
Locate(280,130):DrawText(Str(Time2-Time1))
StopDrawing()
Time1.l = GetTickCount_()
For t=1 To 10000000
;/ Unsigned Signed
a = %00000000
!MOV bl,byte [v_a]
!AND ebx,255
!MOV dword [v_b],ebx ; 0 0
a = %01111111
!MOV bl,byte [v_a]
!AND ebx,255
!MOV dword [v_b],ebx ; 127 127
a = %10000000
!MOV bl,byte [v_a]
!AND ebx,255
!MOV dword [v_b],ebx ; 128 -128
a = %11111111
!MOV bl,byte [v_a]
!AND ebx,255
!MOV dword [v_b],ebx ; 255 -1
Next
Time2.l = GetTickCount_()
StartDrawing(WindowOutput())
FrontColor(0,0,0)
DrawingMode(1)
Locate(20,160):DrawText("Durée direct en ASM (en ms) :")
Locate(280,160):DrawText(Str(Time2-Time1))
StopDrawing()
Repeat
EventID = WaitWindowEvent()
Until EventID = #PB_EventCloseWindow
EndIf
Publié : dim. 22/mai/2005 8:16
par Droopy
Effectivement, Denis a gagné
Je mettrais son code dans (ma) lib
Génial ton test de vitesse de procédure Erix, je met ce code de coté !
Publié : dim. 22/mai/2005 8:39
par Droopy
Me basant sur le code d'Erix14 j'ai créé cette procédure pour mesurer la durée d'exécution d'un bout de code.
Code : Tout sélectionner
; Return the the number of milliseconds between two call
; Cool to Optimize your code
; Idea from Erix14
Procedure MeasureInterval()
Static time
If time
temp=time
time=0
ProcedureReturn GetTickCount_()-temp
Else
time = GetTickCount_()
EndIf
EndProcedure
MeasureInterval()
For n=1 To 10000000 : Next
Debug MeasureInterval()
Publié : dim. 22/mai/2005 9:03
par djes
En regardant le code assembleur avec PureASM, je suis quand même surpris de la taille de la procédure (et de ses initialisations). L'opération en elle-même ne prend au pire que trois instructions, par contre le reste de la procédure (initialisation et restauration de la pile), plus d'une vingtaine, dont une boucle et deux sauts! Autant dire que parler d'optimisation dans ces conditions me laisse un peu... perplexe!
Je me demande si on ne pourrait pas inventer une nouvelle instruction de procedure dont on créerait entièrement le code, sans que pure ne le génére. On pourrait demander à Fred... On pourrait l'appeler ProcedureASM(params) par exemple.
Publié : dim. 22/mai/2005 9:10
par erix14
Tu as fait une erreur dans ta procédure :
Code : Tout sélectionner
Procedure MeasureInterval()
Static time
If time
temp=time
time=0
ProcedureReturn GetTickCount_()-temp
Else
time = GetTickCount_()
EndIf
EndProcedure
MeasureInterval()
Delay(1000)
Debug MeasureInterval()
Delay(1000)
Debug MeasureInterval()
Delay(1000)
Debug MeasureInterval()
Delay(1000)
Debug MeasureInterval()
Delay(1000)
Debug MeasureInterval()
Delay(1000)
Debug MeasureInterval()
voici ma correction :
Code : Tout sélectionner
Procedure MeasureInterval()
Static time
If time
temp=time
time = GetTickCount_()
ProcedureReturn time-temp
Else
time = GetTickCount_()
EndIf
EndProcedure
MeasureInterval()
Delay(1000)
Debug MeasureInterval()
Delay(1000)
Debug MeasureInterval()
Delay(1000)
Debug MeasureInterval()
Delay(1000)
Debug MeasureInterval()
Delay(1000)
Debug MeasureInterval()
Delay(1000)
Debug MeasureInterval()
Publié : dim. 22/mai/2005 9:13
par nico
Le Soldat inconnu avait fait un post dessus sur les conversions des nombres signésmais je ne retrouve pas!
[EDIT] c'est ici:
http://purebasic.hmt-forum.com/viewtopi ... mbre+signe
Publié : dim. 22/mai/2005 9:13
par Droopy
Cette procédure sert à mesurer le temps que met un bout de code à s'exécuter.
Une fois le code optimisé, on n'utilise plus cette procédure !
Publié : dim. 22/mai/2005 9:19
par Anonyme2
Droopy a écrit :Effectivement, Denis a gagné
Je mettrais son code dans (ma) lib
Génial ton test de vitesse de procédure Erix, je met ce code de coté !
Rendons à César...
C'est le code de Fred

Publié : dim. 22/mai/2005 9:22
par Droopy
Pour Erix : Je ne pense pas avoir fait d'erreur, en fait elle permet de mesurer le temps d'exécution de plusieurs bout de code non contigus.
Code : Tout sélectionner
MeasureInterval() ; Initialisation
Delay(500)
Debug MeasureInterval()
; On fait autre chose
Delay(250)
MeasureInterval() ; Initialisation
Delay(800)
Debug MeasureInterval(