$S@g·, g@S$$$ $$$$$$+-ù ú. `@g, .ú- -+g@ ½üýø^_ +-Ä- - $$$$$$-- -Ä-$b,`$-- --- y '-- Ä- -$$ g@S$$$-Ä- ---+ «¬¬«¬ $$$$$$ ¬¬«« $$l $ ¬¬«¬« $ «¬«¬¬«¬ $$ $$$$$$ «¬«¬¬« ¬¬«¬« $$$$$$ ¬«¬¬ $$$ l «¬«¬« $ ¬«¬¬«¬« $$ $(dt)$ ¬«¬¬«¬ +-- Ä -l$$ü$$-Ä-- -$$$ $Ä- --- $`+,._ _,$l $$$$$$-- Ä- -+ $$$y$$ Sü',$ ü $$,øý½SQ$ ½üýø^~ ,g@$$ ,g@S@, $$$l `ýÓ*S,_ _`*S$$b._ ,SSü' This article comes from Hugi issue 15 ú Released in May 1999 ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ OPTIMIZING "GETBITS" PART I TAD ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ OPTIMIZING "GETBITS" PART I ÄÄÄ( TAD )ÄÄÄ Introduction After reading putbits I and II, we all know how to do a 'putbits' routine (right?). So here is the other vital routine for any depacker/decompressor. This document contains tips and advice on how to read a number of bits from a bitstream. Terminology "Bitstream": This is a continuous block of bytes which is used like a huge series of bits. If our bitstream is 100 bits long then we need 13 bytes of storage (actually only 12.5 with 4 bits spare). "BitRack": A temporary byte/word/dword in which bits are shifted out from, or into. "InputByte": This fetches the next byte from our bitstream and passes it back in the AL register. Bit-by-Bit As we are still dealing with a bit-stream, we might as well start with fetching 1 bit at a time from it. Right, we need a counter to record how many bits we have left in the BitRack, and the BitRack itself. Initialise: BitRack = InputByte() BitPos = 7 Get1Bit: newbit = ( BitRack >> BitPos) AND 1 BitPos - 1 If BitPos < 0 then BitRack = InputByte() BitPos = 7 Now, let's use some 80x86 to make life easy. Initialise: call InputByte mov ch, al ; CH = BitRack mov cl, 7 ; Bit = 7 Get1Bit: mov al, ch shr al, cl and al, 1 ; newbit = (BitRack >> BitPos) AND 1 dec cl ; BitPos - 1 jns short notempty ; if BitPos < 0 then call InputByte ; mov ch, al ; BitRack = InputByte() mov cl, 7 ; BitPos = 7 notempty: The bits a-x in the bitstream are stored like this: --------------------> bitstream abcdefgh ijklmnop qrstuvwx .... etc ... byte 0 byte 1 byte 2 Mask and Wrap As you may have already noticed the BitPos counter (register CL) counts down to -1 and then begins again from 7, i.e. it wraps on a power of 2. All the BitPos is currently doing is telling us when the 8th bit has been shifted out of the BitRack. Another way to do this is to use a logical AND instruction to mask off unwanted bits and limit the results to a small range, in this case 8 (7 to 0). E.g. dec cl ; 2 and cl, 00000111b ; 2 jnz short