[Résolu]Nombre double précision et décalage binaire

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
boddhi
Messages : 595
Inscription : lun. 26/avr./2010 16:14
Localisation : S 48° 52' 31'' / O 123° 23' 33''

[Résolu]Nombre double précision et décalage binaire

Message par boddhi »

Bonjour à toutes et à tous,

Après une grande absence sur ce forum liée à une longue pause en programmation, je reviens vers vous pour que vous puissiez m'éclairer sur les décalages binaires, et plus précisément, sur les décalages binaires en 64 bits...
En préambule, pour des besoins personnels, je me suis lancé dans l'écriture d'un code permettant l'extraction de données de fichiers MKV.
Certaines de ces données sont codées en simple précision (32 bits), d'autres le sont en double précision (64 bits donc).

Où l'on en vient aux notions de Signe, d'Exposant et de Mantisse :
  • Sur 32 bits, la représentation binaire d'un simple précision :
  • Signe => Bit 31
  • Exposant => Bits 30 à 23
  • Mantisse => Bits 22 à 0
  • Sur 64 bits, la représentation binaire d'un double précision :
  • Signe => Bit 63
  • Exposant => Bits 62 à 52
  • Mantisse => Bits 51 à 0
Si je n'ai aucun souci pour récupérer ces trois valeurs en simple précision, en revanche le traitement en double précision me pose problème dès la tentative de récupérer le Signe (Bit 63).
Voilà, le bout de code qui devrait me permettre normalement de l'obtenir :

Code : Tout sélectionner

Signe.b=Valeur>>63
Ci-dessous, procédure qui illustre mon problème :

Code : Tout sélectionner

Procedure.d Fc_CalculerDoublePrecision(Valeur.q)
  Define.b Signe,Compteur
  Define.s ChaineBinaire
  
  Debug "Valeur décimale : "+Valeur
  Debug "Valeur hexadécimale : $"+Hex(Valeur)
  ChaineBinaire.s=RSet(Bin(Valeur),64,"0")
  Debug "Chaîne binaire : %"+ChaineBinaire
  Debug "Chaîne binaire découpée : %"+Left(ChaineBinaire,1)+" "+Mid(ChaineBinaire,2,11)+" "+Right(ChaineBinaire,52)

  For Compteur=63 To 0 Step-1
    Debug "Décalage "+RSet(Str(Compteur),2,"0")+" : %"+Bin(Valeur>>Compteur)
  Next

  Signe=Valeur>>63
  Debug "Signe : %"+Bin(Signe)+" => "+Signe
EndProcedure
Pour la valeur 4707240971593580544 ($‭4153 7AB9 4000 0000‬), le décalage se produit correctement et la valeur calculée de Signe est bonne :
Valeur décimale : 4707240971593580544
Valeur hexadécimale : $‭41537AB940000000
Chaîne binaire : %0100000101010011011110101011100101000000000000000000000000000000
Chaîne binaire découpée : %0 10000010101 0011011110101011100101000000000000000000000000000000
Décalage 63 : %0
Décalage 62 : %1
Décalage 61 : %10
Décalage 60 : %100
Décalage 59 : %1000
Décalage 58 : %10000
Décalage 57 : %100000
Décalage 56 : %1000001
................
Décalage 00 : %100000101010011011110101011100101000000000000000000000000000000
Signe : %0 => 0
Or pour la valeur -4516131065261195264 ($C153 7AB9 4000 0000), et le traitement et le résultat ne sont pas corrects (en tout cas, pas ceux que j'attends !)
Là où j'obtiens -1, je devrais avoir 1 :
Valeur décimale : -4516131065261195264
Valeur hexadécimale : $C1537AB940000000
Chaîne binaire : %1100000101010011011110101011100101000000000000000000000000000000
Chaîne binaire découpée : %1 10000010101 0011011110101011100101000000000000000000000000000000
Décalage 63 : %1111111111111111111111111111111111111111111111111111111111111111
Décalage 62 : %1111111111111111111111111111111111111111111111111111111111111111
Décalage 61 : %1111111111111111111111111111111111111111111111111111111111111110
Décalage 60 : %1111111111111111111111111111111111111111111111111111111111111100
Décalage 59 : %1111111111111111111111111111111111111111111111111111111111111000
Décalage 58 : %1111111111111111111111111111111111111111111111111111111111110000
Décalage 57 : %1111111111111111111111111111111111111111111111111111111111100000
Décalage 56 : %1111111111111111111111111111111111111111111111111111111111000001
................
Décalage 00 : %1100000101010011011110101011100101000000000000000000000000000000
Signe : %1111111111111111111111111111111111111111111111111111111111111111 => -1
Pourquoi n'ai-je donc pas :
Décalage 63 : %1
Décalage 62 : %11
Décalage 61 : %110
Décalage 60 : %1100
Décalage 59 : %11000
Décalage 58 : %110000
Décalage 57 : %1100000
Décalage 56 : %11000001
................
Décalage 00 : %1100000101010011011110101011100101000000000000000000000000000000
Je pourrais aisément obtenir les bonnes valeurs avec des RSET(BIN()) et autres VAL() mais cette démarche ne m'intéresse pas (sauf si c'est la seule possibilité), je souhaite avant tout procéder à un traitement purement mathématique...

Quelqu'un aurait-il une idée ?
Merci d'avance pour vos lumières :)
Dernière modification par boddhi le jeu. 31/janv./2019 19:22, modifié 1 fois.
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Re: Nombre double précision et décalage binaire

Message par djes »

C'est très simple, PB utilise les instructions assembleur qui préservent le signe après décalage.
boddhi
Messages : 595
Inscription : lun. 26/avr./2010 16:14
Localisation : S 48° 52' 31'' / O 123° 23' 33''

Re: Nombre double précision et décalage binaire

Message par boddhi »

Bonjour Djes,

Merci d'avoir pris le temps de me répondre.
Après des tests, je constate que c'est une limitation intrinsèque à la nature de la variable Valeur, ici un quad sur 8 octets.
L'existence et l'utilisation d'un hexlet (16 octets) ne produirait pas ce problème.
Je vais donc utiliser une autre approche. En l'occurence, l'utilisation de ABS().

Merci encore :wink:
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Re: [Résolu]Nombre double précision et décalage binaire

Message par djes »

Un petit code vaut mieux qu'un long discours, en mode pas à pas avec le débogueur et si possible en affichage hexa (voir dans les options du débogueur)

Code : Tout sélectionner

valeur.q = -1
EnableASM
MOV rax, valeur
;SAR rax, 63 ;SAR préserve le signe
SHR rax, 63 ;SHR n'en a cure. 
MOV valeur, rax
DisableASM
PB utilise SAR, mais en assembleur, il y a beaucoup d'autres possibilités ! La preuve

Code : Tout sélectionner

valeur.q = -1
signe.b = 0
EnableASM
SUB rax, rax ;Efface rax
ADD rax, valeur
SETS signe ;SETS définit l'opérande si le drapeau SIGN est mis
DisableASM
Debug signe
boddhi
Messages : 595
Inscription : lun. 26/avr./2010 16:14
Localisation : S 48° 52' 31'' / O 123° 23' 33''

Re: [Résolu]Nombre double précision et décalage binaire

Message par boddhi »

Merci Djes.

J'ai analysé tes deux codes via le désassembleur du déboggueur.
Je vois bien le changement de valeur des registres.
C'est didactique mais pour être franc, je ne maîtrise absolument pas la prog en assembleur, c'est donc une voie sur laquelle je ne m'aventurerai pas ! :D

J'ai simplement résolu mon problème par l'ajout d'une ligne :

Code : Tout sélectionner

Signe=Abs(Signe)
après la ligne

Code : Tout sélectionner

Signe=Valeur>>63
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: [Résolu]Nombre double précision et décalage binaire

Message par Ollivier »

Moi je te conseille aussi d'utiliser l'Assembleur.

Code : Tout sélectionner

Procedure RetourneZero()

! mov rax, 0     ; rax = 0

ProcedureReturn

EndProcedure
Pose tes questions dans la rubrique Assembleur, et je me ferai un plaisir d'y répondre. Et j'espère ne pas être le seul.

Je suis un peu différent des autres dans le sens où je préfère bien voir l'Assembleur dicerné du langage PBas natif. Alors j'utilise le point d'exclamation. Et quand tu as une lignée de points d'exclamations, ça décoiffe à plus d'un milliards de lignes "exclamées" par seconde. C'est "macromoléculaire", comme fourrer son oeil dans un microscope (ou un téléscope).

Je ne connaissais pas le terme << hexlet >>. Sympatique ce vocabulaire.
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Re: [Résolu]Nombre double précision et décalage binaire

Message par djes »

Oui, c'est le moment de s'y mettre, surtout vus les défis qu'il s'est lancé. Il n'y a aucune difficulté particulière dans ce cas et ça pourra être utile par la suite.
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: [Résolu]Nombre double précision et décalage binaire

Message par Ollivier »

L'exemple de ExamineAssembly() dans la doc est très instructif pour démarrer.
Répondre