Sign in Join
Wiki copytemporary

Bit manipulation/de: what changed

Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
1-\
2-\
3-
41# Maskierte Operationen
52
63Dieses Beispiel ist ein einfacher Ansatz zur Bit-Manipulation. Das Beispiel bietet den Vorteil, dass Operationen, mit Bit-Gruppen, auf einmal durchgeführt werden.\
74
85``` pascal
96procedure ClearBit(var Value: QWord; Index: Byte);
107begin
118 Value := Value and ((1 shl Index) xor High(QWord)));
129end;
1310
1411procedure SetBit(var Value: QWord; Index: Byte);
1512begin
1613 Value := Value or (QWord(State) shl Index);
1714end;
1815
1916procedure PutBit(var Value: QWord; Index: Byte; State: Boolean);
2017begin
2118 Value := (Value and ((1 shl Index) xor High(QWord))) or (QWord(State) shl Index);
2219end;
2320
2421function GetBit(Value: QWord; Index: Byte): Boolean;
2522begin
2623 Result := ((Value shr Index) and 1) = 1;
2724end;
2825```
2926
30-\
3127=Bitpacked record= Die Verwendung von bitpacked records, wird durch die lokale Compilerdirektive {\$BITPACKING ON} ermöglicht.\
32-\
28+
3329Der 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.\
3430Dies kann man mit einem Record oder einem Array lösen.\
35-\
3631
3732``` pascal
3833 ...
3934
4035 // Compilerdirektive
4136 {$BITPACKING ON}
4237
4338 ...
4439
4540type
4641 TByteBits = bitpacked record
4742 Bit0, Bit1, Bit2, Bit3, Bit4, Bit5, Bit6, Bit7: Boolean;
4843 end;
4944
5045 TByteEx = packed record
5146 case Integer of
5247 0: (ByteAccess: Byte);
5348 1: (BitAccess: TByteBits);
5449 3: (BitArray: bitpacked array[0..7] of Boolean);
5550 end;
5651
5752 ...
5853
5954```
6055
61-\
6256Beispiel für die Verwendung von TByteBits und TByteEx:
6357
6458``` pascal
6559 // Wertzuweisung als Byte
6660 ByteEx.ByteAccess := 4;
6761
6862 // Ändert den Wert von Bit7 und damit den Wert
6963 // der über ByteEx.ByteAccess wieder ausgelesen wird
7064 // in diesem Beispiel beträgt der Wert in
7165 // ByteEx.ByteAccess 132
7266 ByteEx.BitAccess.Bit7 := True;
7367
7468 // Über die Array
7569 ByteEx.BitArray[7] := True;
7670```
7771
78-\
79-
8072# Set
8173
82-\
8374In Sets kann man die Bits eintragen, die für die Bitmanipulation in frage kommen.\
8475
8576``` pascal
8677
8778 ...
8879
8980 // Compilerdirektiven
9081 {$packset 1}
9182 {$packenum 1}
9283
9384 ...
9485
9586 type
9687 TSetByteBits = set of (Bit0, Bit1, Bit2, Bit3, Bit4, Bit5, Bit6, Bit7);
9788
9889 ...
9990
10091 var
10192 SetByteBits: TSetByteBits;
10293 ...
10394
10495 begin
10596
10697 ...
10798
10899 // legt fest, welche Elemente im Set gespeichert werden
109100 SetByteBits := [Bit0 .. Bit7];
110101
111102 // Startet eine Bitmanipulation, wenn Bit3 im Set gefunden wird
112103 if Bit3 in SetByteBits then
113104 begin
114105 ...
115106 end;
116107
117108 ...
118109
119110 end;
120111
121112 ...
122113
123114```
124115
125-\
126-
127116# TBits
128117
129-\
130118Diese Klasse ist Teil der Klasse Unit aus der Free Pascal RTL Bibliothek. Die Klasse bietet einige Methoden zur Bit-Manipulation.
131119
132120``` pascal
133121 TBits = class(TObject)
134122 public
135123 constructor Create(TheSize : longint = 0); virtual;
136124 destructor Destroy; override;
137125 function GetFSize : longint;
138126 procedure SetOn(Bit : longint);
139127 procedure Clear(Bit : longint);
140128 procedure Clearall;
141129 procedure AndBits(BitSet : TBits);
142130 procedure OrBits(BitSet : TBits);
143131 procedure XorBits(BitSet : TBits);
144132 procedure NotBits(BitSet : TBits);
145133 function Get(Bit : longint) : boolean;
146134 procedure Grow(NBit : longint);
147135 function Equals(Obj : TObject): Boolean; override; overload;
148136 function Equals(BitSet : TBits) : Boolean; overload;
149137 procedure SetIndex(Index : longint);
150138 function FindFirstBit(State : boolean) : longint;
151139 function FindNextBit : longint;
152140 function FindPrevBit : longint;
153141
154142 // Funktionen und Eigenschaften zu entsprechen TBits class
155143 function OpenBit: longint;
156144 property Bits[Bit: longint]: Boolean read get write SetBit; default;
157145 property Size: longint read FBSize write setSize;
158146 end;
159147```
160148
161-\
162149Beispiel für eine Verwendung:
163150
164151``` pascal
165152 ...
166153
167154 var
168155 Bits: TBits;
169156 bytI: Byte;
170157
171158 begin
172159
173160 ...
174161
175162 // Erstellt das Objekt
176163 Bits := TBits.Create;
177164
178165 // Legt die Grösse fest
179166 Bits.Size := 5;
180167
181168 // legt für einige Bits den Wert fest
182169 Bits[0] := true;
183170 Bits[1] := true;
184171 Bits[4] := true;
185172
186173 // Ausagbe der Werte
187174 for bytI := 0 to Bits.Size-1 do
188175 if Bits[bytI] = true
189176 then ShowMessage(inttostr(bytI) + ' ' + BoolToStr(Bits[bytI]))
190177 else ShowMessage(inttostr(bytI) + ' ' + BoolToStr(Bits[bytI]));
191178
192179 // gibt den Speicher des Objektes wieder frei
193180 Bits.Free;
194181
195182 ...
196183
197184 end;
198185
199186 ...
200187```
201188
202-\
203189=Record Eigenschaften und Wertindex=\
204190Another 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.
205191
206192``` pascal
207193{$mode delphi}
208194
209195 TSomeBitStructure = record
210196 private
211197 RawData: Word;
212198 function GetBits(const AIndex: Integer): Integer; inline;
213199 procedure SetBits(const AIndex: Integer; const AValue: Integer); inline;
214200 public
215201 // High byte of index offset, low byte of index is bit count
216202 property OneBit: Integer index $0001 read GetBits write SetBits;
217203 property TwoBits: Integer index $0102 read GetBits write SetBits;
218204 property FourBits: Integer index $0304 read GetBits write SetBits;
219205 property EightBits: Integer index $0708 read GetBits write SetBits;
220206 end;
221207
222208{$OPTIMIZATION ON}
223209{$OVERFLOWCHECKS OFF}
224210function TSomeBitStructure.GetBits(const AIndex: Integer): Integer;
225211var
226212 Offset: Integer;
227213 BitCount: Integer;
228214 Mask: Integer;
229215begin
230216 BitCount := AIndex and $FF;
231217 Offset := AIndex shr 8;
232218 Mask := ((1 shl BitCount) - 1);
233219 Result := (RawData shr Offset) and Mask;
234220end;
235221
236222procedure TSomeBitStructure.SetBits(const AIndex: Integer; const AValue: Integer);
237223var
238224 Offset: Integer;
239225 BitCount: Integer;
240226 Mask: Integer;
241227begin
242228 BitCount := AIndex and $FF;
243229 Offset := AIndex shr 8;
244230 Mask := ((1 shl BitCount) - 1);
245231 Assert(aValue <= Mask);
246232 RawData := (RawData and (not (Mask shl Offset))) or (AValue shl Offset);
247233end;
248234```
249235
250236---
251237*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).*

Back to history