Conversion d'octets signés en non signés

Partagez votre expérience de PureBasic avec les autres utilisateurs.
erix14
Messages : 480
Inscription : sam. 27/mars/2004 16:44
Contact :

Message par erix14 »

Droopy a écrit :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 !
En fait pour qui n'est pas d'ambiguïté, tu devrais faire deux procédures :
- StartMeasureInterval()
- StopMeasureInterval()
Avatar de l’utilisateur
Droopy
Messages : 1151
Inscription : lun. 19/juil./2004 22:31

Message par Droopy »

Le code du Soldat est le même que Fred ! :D
Avatar de l’utilisateur
Droopy
Messages : 1151
Inscription : lun. 19/juil./2004 22:31

Message par Droopy »

T'as raison Erix je vais faire 2 procédures
- StartMeasureInterval()
- StopMeasureInterval()

très bonne idée !
Dr. Dri
Messages : 2527
Inscription : ven. 23/janv./2004 18:10

Message par Dr. Dri »

Faut arrêter d'abuser de GetTickCount ^^
y'a ElapsedMilliseconds() Maintenant ;)

Dri
Anonyme2
Messages : 3518
Inscription : jeu. 22/janv./2004 14:31
Localisation : Sourans

Message par Anonyme2 »

djes a écrit :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.
C'est un des gros avantage d'écrire une librairie en asm (voire en C mais là je n'y connais que dalle) car PB ne permet pas de le faire directement.

Tu as remarqué, PB alloue de la place qur la pile pour toutes les variables et tous les paramètres; ensuite PB recopie l'ensemble des paramètres sur la pile puis initialise les variables locales à 0, le tout en ayant sauvegardé tous les registres sauf eax et edx. Ce n'est pas une critique, il faut bien avoir des règles.

Le code PB

Code : Tout sélectionner

; Procedure.b SignedBinaryToUnsigned(Byte.b)
	JMP	 _EndProcedure0
_Procedure0:
	PUSH	 ebx
	PUSH	 ecx
	PUSH	 ebp
	PUSH	 esi
	PUSH	 edi
	MOV	 esi,esp
	SUB	 esp,4
	MOV	 eax,esp
	MOV	 edx,eax
	ADD	 edx,4
_ClearLoop0:
	MOV	 dword [eax],0
	ADD	 eax,4
	CMP	 eax,edx
	JNE	 _ClearLoop0                                                                                                                    
	MOV	 eax, dword [esi+24]
	MOV	 byte [esp+0],al
; ProcedureReturn Byte & $FF
	MOVSX	 ebx,byte [esp]
	AND	 ebx,255
	MOV	 eax,ebx
	JMP	 _EndProcedure1
; EndProcedure
	XOR	 eax,eax
_EndProcedure1:
	ADD	 esp,4
	POP	 edi
	POP	 esi
	POP	 ebp
	POP	 ecx
	POP	 ebx
	RET	 4
_EndProcedure0:
et l'équivalent avec PureASMTools (intégré à PureASM) pour la génération du squelette asm

Code : Tout sélectionner

format MS COFF
public PB_SignedBinaryToUnsigned_ASM

; -------------------------------------------;
;        Paramètres d'entrée                 ;
; -------------------------------------------;

; Byte.b
Byte   equ esp+4

; -------------------------------------------;
;        Section code                        ;
; -------------------------------------------;

section '.text' code readable executable

PB_SignedBinaryToUnsigned_ASM:



; **************************************************
; Mettez votre code asm perso après cette ligne


	MOVSX	 eax,byte [Byte]
	AND	   eax,255


; fin de la zone de votre code asm perso 
; **************************************************


_Retour:
	RET	 4

J'espère que PureASMTools donnera envie à certains de faire des libs en asm (Bon, tout n'est pas parfait mais je travaille un peu dessus tous les jours, surtout la doc en ce moment)
Dernière modification par Anonyme2 le dim. 22/mai/2005 12:16, modifié 1 fois.
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Message par djes »

Denis> Effectivement, là, ça devient intéressant! J'avoue que je n'avais pas trop regardé tout ça... La création de libs ne m'intéresse pas vraiment, mais apparemment cet outil peut être très utile!!! Personnellement, je vais y jeter un oeil attentif.

Droopy> Pourquoi t'essayes pas QueryPerformanceCounter_(@time) ? :)
Avatar de l’utilisateur
Droopy
Messages : 1151
Inscription : lun. 19/juil./2004 22:31

Message par Droopy »

c'est effectivement plus simple comme ça :

Code : Tout sélectionner

; Return the the number of milliseconds between two call
; Cool to Optimize your code
; Idea from Erix14


Global MeasureIntervalTime.l

ProcedureDLL MeasureIntervalStart()
  MeasureIntervalTime=ElapsedMilliseconds()
EndProcedure

ProcedureDLL MeasureIntervalStop()
  ProcedureReturn ElapsedMilliseconds()-MeasureIntervalTime
EndProcedure

MeasureIntervalStart()
Delay(250)
Debug MeasureIntervalStop()
J'ai utilisé ElapsedMilliseconds() : Merci Dr Dri
J'ai l'air ridicule face aux procédures en assembleur de Denis :oops:
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

J'ai l'air ridicule face aux procédures en assembleur de Denis Embarassed
tu avait deja l'air ridicule avec ton images de pseudo !! :lol: :lol:
franchement ! un chien qui pilote un avion jaune :lol:




:lol: :lol: :lol: :lol: :lol: :lol: :lol: :lol: :lol: :lol: :lol: :lol: :lol:
:lol: :lol: :lol: :lol: :lol: :lol: :lol: :lol: :lol: :lol: :lol: :lol: :lol:
Dernière modification par Backup le dim. 22/mai/2005 12:22, modifié 1 fois.
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Message par djes »

J'ai fait un petit test vite fait avec les timers haute résolution.

Code : Tout sélectionner

;*** Normalement, les fonctions renvoient des entiers de 64 bits. On réserve donc 
;    deux entiers de 32 bits pour stocker cette valeur, même si dans cet exemple, 
;    on ne s'en servira pas

Dim freq.l(2)
Dim time.l(2)

Procedure MeasureInterval()
     If time(1)
          temp=time(0)
          QueryPerformanceCounter_(@time(0))
          ProcedureReturn time(0)-temp
     Else
          QueryPerformanceCounter_(@time(0))
     EndIf
EndProcedure

;*** Y-a-t-il un compteur haute résolution?

If QueryPerformanceFrequency_(@freq(0))

 ;*** Renvoie la fréquence de notre compteur (seuls les 32 premiers bits)
 Debug freq(0)

 ;*** Effectue une dizaine de tests
 MeasureInterval()
 For i=0 To 9
  Delay(1000)  
  Debug MeasureInterval()
 Next
EndIf

End
Anonyme2
Messages : 3518
Inscription : jeu. 22/janv./2004 14:31
Localisation : Sourans

Message par Anonyme2 »

Dobro a écrit :franchemant ! un chien qui pilote un avion jaune :lol:

Ca me rapelle un dessin animé que je ragardais il y a pas mal d'années, je ne me souviens plus du nom mais il me semble que ça repasse sur le cable
Avatar de l’utilisateur
Droopy
Messages : 1151
Inscription : lun. 19/juil./2004 22:31

Message par Droopy »

Code modifié avec le timer haute résolution

Code : Tout sélectionner

; Idea from Erix14
; Return the time elapsed between Start & Stop in second
; 0.001 = 1 ms
; 0.000001=1 µs

Global MeasureIntervalTime.l

ProcedureDLL MeasureIntervalStart()
QueryPerformanceCounter_(@MeasureIntervalTime)  
EndProcedure

ProcedureDLL.f MeasureIntervalStop()
  QueryPerformanceCounter_(@Temp)
  Difference=Temp-MeasureIntervalTime
  QueryPerformanceFrequency_(@HiResTimerFrequency)
  Periode.f=1/HiResTimerFrequency
  DureeTotale.f=Difference*Periode
  ProcedureReturn DureeTotale
EndProcedure

;/ Test
MeasureIntervalStart()
Delay(150)
Debug MeasureIntervalStop()
merci Djes
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Message par djes »

Euh oui mais à mon avis il faut garder les deux : dans la doc de Microsoft, il est dit que le timer haute résolution n'est pas implémenté sur toutes les machines.

En outre, n'oublie pas que la valeur renvoyée est sur 64bits, attention donc car les fonctions écrasent certainement des données quelque part.
Avatar de l’utilisateur
Droopy
Messages : 1151
Inscription : lun. 19/juil./2004 22:31

Message par Droopy »

OK j'ai ajouté un test pour savoir si le matériel le supporte
Je conseillerais cette procédure pour les test < ms
et l'ancienne pour celles > ms

Code : Tout sélectionner

; Idea from Erix14 / Djes
; Return the time elapsed between Start & Stop in second
; 0.001 = 1 ms
; 0.000001=1 µs
; Caution ! : If the installed hardware supports a high-resolution performance counter
; MeasureIntervalHiResStart return 1 / 0 if no hardware support 

Global MeasureIntervalTime.l

ProcedureDLL MeasureIntervalHiResStart()
  QueryPerformanceFrequency_(@retour)
  If retour <>0 : retour = 1 : EndIf
  QueryPerformanceCounter_(@MeasureIntervalTime)  
  ProcedureReturn retour
EndProcedure

ProcedureDLL.f MeasureIntervalHiResStop()
  QueryPerformanceCounter_(@Temp)
  Difference=Temp-MeasureIntervalTime
  QueryPerformanceFrequency_(@HiResTimerFrequency)
  Periode.f=1/HiResTimerFrequency
  DureeTotale.f=Difference*Periode
  ProcedureReturn DureeTotale
EndProcedure

;/ Test
If MeasureIntervalHiResStart()
  Delay(1)
  Debug MeasureIntervalHiResStop()
EndIf
Répondre