Page 1 sur 1

Champs de bits / Variables de taille n bits

Publié : dim. 29/avr./2018 15:45
par Naheulf
Bonjour à tous et à toutes,

Est-ce que quelqu’un(e) sait comment déclarer une structure avec des champs qui ne sont pas des multiples d’un octet ?

Je voudrais arriver à faire l’équivalent du code C suivant :

Code : Tout sélectionner

struct CompressedChunkHeader{
     unsigned size:12;
     unsigned signature:3;
     unsigned flag:1;
     unsigned reserved:16:
};
L'idéal serait bien évidement de pouvoir accéder aux valeurs avec un simple

Code : Tout sélectionner

Structure CompressedChunkHeader [Align 0.125]
    size.???
    signature.???
    flag.???
    reserved.w
EndStructure

maStructure.CompressedChunkHeader
maStructure\size = 9
;some code
If maStructure\signature <> sommeDeControle
    ; erreur
EndIf
D'après ce que j'ai vu il faut nécessairement passer par les opérateurs binaires. "&", "|", "<<" et ">>".

Re: Champs de bits / Variables de taille n bits

Publié : dim. 29/avr./2018 16:57
par nico
Oui, il faut passer par les opérateurs binaires. Il est possible aussi de le faire en passant par des chaines de caractères.

Tiens, je te fais un exemple ici:
Dans cet exemple, je prend les valeurs en commençant par le bit de poids fort vers le bit de poids faible, on peut faire l'inverse mais c'est pas forcément nécessaire et utile de rajouter du code en plus dans notre cas.
[Edit] modification du code, travaille avec 8, 16, 32 ou 64 bit

Code : Tout sélectionner

Structure CompressedChunkHeader
    ;  la valeur ChunkHeader qui nous intéresse qui sera répartie dans les variables qui suivent après traitement.
    ChunkHeader.l
    size.l
    signature.l
    flag.l
    reserved.l
EndStructure
 
Procedure.q bit(Valeur.q, PositionDepart.l, Longueur.l, nbBit.l)
    Protected Valeur$
    
    Valeur$ = Bin(Valeur, #PB_Quad)
    Valeur$ = RSet(Valeur$, nbBit, "0")
    Debug Valeur$
    Valeur$ = Mid(Valeur$, PositionDepart, Longueur) 
    Debug Valeur$
    Valeur = Val("%" + Valeur$)
    
    ProcedureReturn Valeur
EndProcedure


test.CompressedChunkHeader\ChunkHeader = %00101111000011110101111100001111
                                              
test\size =  bit(test\ChunkHeader, 1, 12, 32)
Debug test\size

test\signature =  bit(test\ChunkHeader, 13, 3, 32)
Debug test\signature

test\flag =  bit(test\ChunkHeader, 16, 1, 32)
Debug test\flag

test\reserved = bit(test\ChunkHeader, 17, 16, 32)
Debug test\reserved

Re: Champs de bits / Variables de taille n bits

Publié : dim. 29/avr./2018 16:59
par Fig
A ma connaissance, en Pb il est nativement impossible d'accéder à des bits, encore moins d'utiliser une structure non multiple de l'octet.
Il faut utiliser les opérateurs binaires et cela complique légèrement le code.

Re: Champs de bits / Variables de taille n bits

Publié : dim. 29/avr./2018 17:11
par GallyHC
Bonjour,

Je penses juste que pour la signature, on peut faire "signature.s{3}", après j'avoue que je ne sais pas.

Cordialement,
GallyHC

Re: Champs de bits / Variables de taille n bits

Publié : dim. 29/avr./2018 17:12
par nico
Mais pourquoi intervenir pour simplement répéter ce qui est déjà écrit précédemment?

Re: Champs de bits / Variables de taille n bits

Publié : dim. 29/avr./2018 17:17
par GallyHC
Bonjour,
nico a écrit :Mais pourquoi intervenir pour simplement répéter ce qui est déjà écrit précédemment?
C'est pour qui cette phrase?

GallyHC

Re: Champs de bits / Variables de taille n bits

Publié : dim. 29/avr./2018 17:18
par Fig
nico a écrit :Mais pourquoi intervenir pour simplement répéter ce qui est déjà écrit précédemment?
Si ça me concerne, tu as posté alors que j'écrivais moi aussi, tout simplement.

Re: Champs de bits / Variables de taille n bits

Publié : dim. 29/avr./2018 17:22
par nico
Ok, déolé.

Re: Champs de bits / Variables de taille n bits

Publié : dim. 29/avr./2018 17:33
par Ollivier
Moi, j'ai une technique de psychopathe : chaque bit est un entier signé de 64 bits de type quad. Tu extrais l'info, tu lis et modifies l'info, puis tu la recomprime en bits.

Code : Tout sélectionner

Structure Psychostruc
    Size.I[12]
    Signature.I[3]
    Flag.I
    Reserved.I[16]
EndStructure
Une fois que c'est modifié, plié... Hop, recompression ICI

Re: Champs de bits / Variables de taille n bits

Publié : dim. 29/avr./2018 22:14
par G-Rom
ton code en C correspond a cela en PB :

Code : Tout sélectionner

Structure CompressedChunkHeader
    reserved.l
EndStructure
Il faut que tu joue avec les bits pour accéder aux éléments, attention a la capacité des champs, 12 bits , c'est moins qu'un word, environ +/- 2047
soit en gros :

Code : Tout sélectionner

Structure CompressedChunkHeader
    reserved.l
EndStructure


Macro setSize(struct, size)
 struct\reserved = struct\reserved &FFF | (size<<19)  
EndMacro

Macro getSize(struct)
  struct\reserved >> 19 & $FFF
EndMacro

Macro setSignature(struct, size)
  struct\reserved = struct\reserved | (size<<15)
EndMacro

Macro getSignature(struct)
  struct\reserved >> 15 & $F
EndMacro

Macro setFlag(struct, bit)
  If bit=1
    struct\reserved  | (1<<14) 
  Else
    struct\reserved & (254 << 14)
  EndIf  
EndMacro

Macro getFlag(struct)
  Struct\reserved >> 14 & $1
EndMacro


A.CompressedChunkHeader
A\reserved = 0
setSize(A,245)
setSignature(A,15)
setFlag(A,1)

Debug RSet(Bin(A\reserved),32,"0")

 Debug getSize(A)
 Debug getSignature(A)
 Debug getFlag(A)

Re: Champs de bits / Variables de taille n bits

Publié : lun. 30/avr./2018 19:04
par Ollivier
Tiens, ça m'étonne que ce soit en little endian les champs de bits en C.

Si c'est le cas, mon code de compression de quads booléens en bits est à mettre au placard !

Re: Champs de bits / Variables de taille n bits

Publié : lun. 30/avr./2018 19:35
par G-Rom
J'ai pas pris en compte l'endianess, tu peu changer mon code pour changé les bits dans l'ordre qui t'arrange.

Re: Champs de bits / Variables de taille n bits

Publié : jeu. 03/mai/2018 8:29
par Ollivier
J'ai essayé de trouver une soluce à la fois proche de la syntaxe actuelle (structure+lecture+écriture) en maintenant la performance : impossible.

La syntaxe bloque. Et la structuration (créer une structure avec des champs variable en fonction des arguments d'une macro) bloque aussi.

Le seul petit truc que j'ai "réussi" à pondre, c'est le masque d'un champ :

Code : Tout sélectionner

Macro BitMask(BitStart, BitLength)
   (((1 << BitLength) - 1) << BitStart)
EndMacro
C'est en big endian à base 0 pour BitStart et en bits pour BitLength.

Le problème, c'est que c'est quasiment impossible d'obtenir les deux arguments BitStart et BitLength sous forme de constante pré-calculée à partir d'une liste de directive de type

Code : Tout sélectionner

bStruc(maStruc,
Champs1,3,
Champs2,2,
DernierChamps,11)
J'arrive à obtenir des suites polynomiales avec les macros. Par exemple

Code : Tout sélectionner

Debug myMacro
Debug myMacro
Debug myMacro
Debug myMacro
qui donne

Code : Tout sélectionner

1
3
6
10
mais je n'arrive pas à faire un calcul de type "oignon" avec les macros.
De ce type:

Code : Tout sélectionner

0
0+3
0+3+2
0+3+2+11
sachant que si toutes ces valeurs sont des constantes ou des arguments de macros, elles peuvent être stockées dans des constantes et donc être précalculées.

Re: Champs de bits / Variables de taille n bits

Publié : sam. 05/mai/2018 19:50
par Naheulf
Merci pour toutes vos réponses.

Au moins c'est clair : Il n'y a plus qu'à se faire sa propre tambouille pour accéder aux bits.

Merci à tous