Bit manipulation/de: what changed
Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.
Title: Bit manipulation/de
| Old | New | Line | |
|---|---|---|---|
| 1 | + | \ | |
| 2 | + | \ | |
| 3 | + | ||
| 4 | + | # Maskierte Operationen | |
| 5 | + | ||
| 6 | + | Dieses Beispiel ist ein einfacher Ansatz zur Bit-Manipulation. Das Beispiel bietet den Vorteil, dass Operationen, mit Bit-Gruppen, auf einmal durchgeführt werden.\ | |
| 7 | + | ||
| 8 | + | ``` pascal | |
| 9 | + | procedure ClearBit(var Value: QWord; Index: Byte); | |
| 10 | + | begin | |
| 11 | + | Value := Value and ((1 shl Index) xor High(QWord))); | |
| 12 | + | end; | |
| 13 | + | ||
| 14 | + | procedure SetBit(var Value: QWord; Index: Byte); | |
| 15 | + | begin | |
| 16 | + | Value := Value or (QWord(State) shl Index); | |
| 17 | + | end; | |
| 18 | + | ||
| 19 | + | procedure PutBit(var Value: QWord; Index: Byte; State: Boolean); | |
| 20 | + | begin | |
| 21 | + | Value := (Value and ((1 shl Index) xor High(QWord))) or (QWord(State) shl Index); | |
| 22 | + | end; | |
| 23 | + | ||
| 24 | + | function GetBit(Value: QWord; Index: Byte): Boolean; | |
| 25 | + | begin | |
| 26 | + | Result := ((Value shr Index) and 1) = 1; | |
| 27 | + | end; | |
| 28 | + | ``` | |
| 29 | + | ||
| 30 | + | \ | |
| 31 | + | =Bitpacked record= Die Verwendung von bitpacked records, wird durch die lokale Compilerdirektive {\$BITPACKING ON} ermöglicht.\ | |
| 32 | + | \ | |
| 33 | + | Der Free Pascal Compiler bietet die Möglichkeit einzelne Bits im Speicher anzusprechen. Mit dem Beispiel kann sowohl das ganze Byte als auch das einzelne Bit in diesem Byte angeprochen werden.\ | |
| 34 | + | Dies kann man mit einem Record oder einem Array lösen.\ | |
| 35 | + | \ | |
| 36 | + | ||
| 37 | + | ``` pascal | |
| 38 | + | ... | |
| 39 | + | ||
| 40 | + | // Compilerdirektive | |
| 41 | + | {$BITPACKING ON} | |
| 42 | + | ||
| 43 | + | ... | |
| 44 | + | ||
| 45 | + | type | |
| 46 | + | TByteBits = bitpacked record | |
| 47 | + | Bit0, Bit1, Bit2, Bit3, Bit4, Bit5, Bit6, Bit7: Boolean; | |
| 48 | + | end; | |
| 49 | + | ||
| 50 | + | TByteEx = packed record | |
| 51 | + | case Integer of | |
| 52 | + | 0: (ByteAccess: Byte); | |
| 53 | + | 1: (BitAccess: TByteBits); | |
| 54 | + | 3: (BitArray: bitpacked array[0..7] of Boolean); | |
| 55 | + | end; | |
| 56 | + | ||
| 57 | + | ... | |
| 58 | + | ||
| 59 | + | ``` | |
| 60 | + | ||
| 61 | + | \ | |
| 62 | + | Beispiel für die Verwendung von TByteBits und TByteEx: | |
| 63 | + | ||
| 64 | + | ``` pascal | |
| 65 | + | // Wertzuweisung als Byte | |
| 66 | + | ByteEx.ByteAccess := 4; | |
| 67 | + | ||
| 68 | + | // Ändert den Wert von Bit7 und damit den Wert | |
| 69 | + | // der über ByteEx.ByteAccess wieder ausgelesen wird | |
| 70 | + | // in diesem Beispiel beträgt der Wert in | |
| 71 | + | // ByteEx.ByteAccess 132 | |
| 72 | + | ByteEx.BitAccess.Bit7 := True; | |
| 73 | + | ||
| 74 | + | // Über die Array | |
| 75 | + | ByteEx.BitArray[7] := True; | |
| 76 | + | ``` | |
| 77 | + | ||
| 78 | + | \ | |
| 79 | + | ||
| 80 | + | # Set | |
| 81 | + | ||
| 82 | + | \ | |
| 83 | + | In Sets kann man die Bits eintragen, die für die Bitmanipulation in frage kommen.\ | |
| 84 | + | ||
| 85 | + | ``` pascal | |
| 86 | + | ||
| 87 | + | ... | |
| 88 | + | ||
| 89 | + | // Compilerdirektiven | |
| 90 | + | {$packset 1} | |
| 91 | + | {$packenum 1} | |
| 92 | + | ||
| 93 | + | ... | |
| 94 | + | ||
| 95 | + | type | |
| 96 | + | TSetByteBits = set of (Bit0, Bit1, Bit2, Bit3, Bit4, Bit5, Bit6, Bit7); | |
| 97 | + | ||
| 98 | + | ... | |
| 99 | + | ||
| 100 | + | var | |
| 101 | + | SetByteBits: TSetByteBits; | |
| 102 | + | ... | |
| 103 | + | ||
| 104 | + | begin | |
| 105 | + | ||
| 106 | + | ... | |
| 107 | + | ||
| 108 | + | // legt fest, welche Elemente im Set gespeichert werden | |
| 109 | + | SetByteBits := [Bit0 .. Bit7]; | |
| 110 | + | ||
| 111 | + | // Startet eine Bitmanipulation, wenn Bit3 im Set gefunden wird | |
| 112 | + | if Bit3 in SetByteBits then | |
| 113 | + | begin | |
| 114 | + | ... | |
| 115 | + | end; | |
| 116 | + | ||
| 117 | + | ... | |
| 118 | + | ||
| 119 | + | end; | |
| 120 | + | ||
| 121 | + | ... | |
| 122 | + | ||
| 123 | + | ``` | |
| 124 | + | ||
| 125 | + | \ | |
| 126 | + | ||
| 127 | + | # TBits | |
| 128 | + | ||
| 129 | + | \ | |
| 130 | + | Diese Klasse ist Teil der Klasse Unit aus der Free Pascal RTL Bibliothek. Die Klasse bietet einige Methoden zur Bit-Manipulation. | |
| 131 | + | ||
| 132 | + | ``` pascal | |
| 133 | + | TBits = class(TObject) | |
| 134 | + | public | |
| 135 | + | constructor Create(TheSize : longint = 0); virtual; | |
| 136 | + | destructor Destroy; override; | |
| 137 | + | function GetFSize : longint; | |
| 138 | + | procedure SetOn(Bit : longint); | |
| 139 | + | procedure Clear(Bit : longint); | |
| 140 | + | procedure Clearall; | |
| 141 | + | procedure AndBits(BitSet : TBits); | |
| 142 | + | procedure OrBits(BitSet : TBits); | |
| 143 | + | procedure XorBits(BitSet : TBits); | |
| 144 | + | procedure NotBits(BitSet : TBits); | |
| 145 | + | function Get(Bit : longint) : boolean; | |
| 146 | + | procedure Grow(NBit : longint); | |
| 147 | + | function Equals(Obj : TObject): Boolean; override; overload; | |
| 148 | + | function Equals(BitSet : TBits) : Boolean; overload; | |
| 149 | + | procedure SetIndex(Index : longint); | |
| 150 | + | function FindFirstBit(State : boolean) : longint; | |
| 151 | + | function FindNextBit : longint; | |
| 152 | + | function FindPrevBit : longint; | |
| 153 | + | ||
| 154 | + | // Funktionen und Eigenschaften zu entsprechen TBits class | |
| 155 | + | function OpenBit: longint; | |
| 156 | + | property Bits[Bit: longint]: Boolean read get write SetBit; default; | |
| 157 | + | property Size: longint read FBSize write setSize; | |
| 158 | + | end; | |
| 159 | + | ``` | |
| 160 | + | ||
| 161 | + | \ | |
| 162 | + | Beispiel für eine Verwendung: | |
| 163 | + | ||
| 164 | + | ``` pascal | |
| 165 | + | ... | |
| 166 | + | ||
| 167 | + | var | |
| 168 | + | Bits: TBits; | |
| 169 | + | bytI: Byte; | |
| 170 | + | ||
| 171 | + | begin | |
| 172 | + | ||
| 173 | + | ... | |
| 174 | + | ||
| 175 | + | // Erstellt das Objekt | |
| 176 | + | Bits := TBits.Create; | |
| 177 | + | ||
| 178 | + | // Legt die Grösse fest | |
| 179 | + | Bits.Size := 5; | |
| 180 | + | ||
| 181 | + | // legt für einige Bits den Wert fest | |
| 182 | + | Bits[0] := true; | |
| 183 | + | Bits[1] := true; | |
| 184 | + | Bits[4] := true; | |
| 185 | + | ||
| 186 | + | // Ausagbe der Werte | |
| 187 | + | for bytI := 0 to Bits.Size-1 do | |
| 188 | + | if Bits[bytI] = true | |
| 189 | + | then ShowMessage(inttostr(bytI) + ' ' + BoolToStr(Bits[bytI])) | |
| 190 | + | else ShowMessage(inttostr(bytI) + ' ' + BoolToStr(Bits[bytI])); | |
| 191 | + | ||
| 192 | + | // gibt den Speicher des Objektes wieder frei | |
| 193 | + | Bits.Free; | |
| 194 | + | ||
| 195 | + | ... | |
| 196 | + | ||
| 197 | + | end; | |
| 198 | + | ||
| 199 | + | ... | |
| 200 | + | ``` | |
| 201 | + | ||
| 202 | + | \ | |
| 203 | + | =Record Eigenschaften und Wertindex=\ | |
| 204 | + | Another interesting implementation of bit aligned structure can be used with capabilities of advanced records (FPC 2.6.0+). For all properties you have to use setter and getter which can handle general bit manipulations and set index which is passed to these methods. For more information refer to [Indexed properties](http://www.freepascal.org/docs-html/ref/refsu31.html). Because index is only one, it has to be divided to two parameters to describe location and size on bit value. In case of the following example, the offset can be 0..255 and size of value 0..255 bits. Another problem is that you have to ensure that defined structure components will not overlay. | |
| 205 | + | ||
| 206 | + | ``` pascal | |
| 207 | + | {$mode delphi} | |
| 208 | + | ||
| 209 | + | TSomeBitStructure = record | |
| 210 | + | private | |
| 211 | + | RawData: Word; | |
| 212 | + | function GetBits(const AIndex: Integer): Integer; inline; | |
| 213 | + | procedure SetBits(const AIndex: Integer; const AValue: Integer); inline; | |
| 214 | + | public | |
| 215 | + | // High byte of index offset, low byte of index is bit count | |
| 216 | + | property OneBit: Integer index $0001 read GetBits write SetBits; | |
| 217 | + | property TwoBits: Integer index $0102 read GetBits write SetBits; | |
| 218 | + | property FourBits: Integer index $0304 read GetBits write SetBits; | |
| 219 | + | property EightBits: Integer index $0708 read GetBits write SetBits; | |
| 220 | + | end; | |
| 221 | + | ||
| 222 | + | {$OPTIMIZATION ON} | |
| 223 | + | {$OVERFLOWCHECKS OFF} | |
| 224 | + | function TSomeBitStructure.GetBits(const AIndex: Integer): Integer; | |
| 225 | + | var | |
| 226 | + | Offset: Integer; | |
| 227 | + | BitCount: Integer; | |
| 228 | + | Mask: Integer; | |
| 229 | + | begin | |
| 230 | + | BitCount := AIndex and $FF; | |
| 231 | + | Offset := AIndex shr 8; | |
| 232 | + | Mask := ((1 shl BitCount) - 1); | |
| 233 | + | Result := (RawData shr Offset) and Mask; | |
| 234 | + | end; | |
| 235 | + | ||
| 236 | + | procedure TSomeBitStructure.SetBits(const AIndex: Integer; const AValue: Integer); | |
| 237 | + | var | |
| 238 | + | Offset: Integer; | |
| 239 | + | BitCount: Integer; | |
| 240 | + | Mask: Integer; | |
| 241 | + | begin | |
| 242 | + | BitCount := AIndex and $FF; | |
| 243 | + | Offset := AIndex shr 8; | |
| 244 | + | Mask := ((1 shl BitCount) - 1); | |
| 245 | + | Assert(aValue <= Mask); | |
| 246 | + | RawData := (RawData and (not (Mask shl Offset))) or (AValue shl Offset); | |
| 247 | + | end; | |
| 248 | + | ``` | |
| 249 | + | ||
| 250 | + | --- | |
| 251 | + | *From the Free Pascal wiki, page "Bit manipulation/de", as it stood on 2020-02-10 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).* |
