Really need to understand bitpacking and unpacking and masking.

Started by BytePtr, February 14, 2010, 11:51:57 AM

Previous topic - Next topic

BytePtr

I know it sounds weird since i have coded many apps using assembly language. Unpacked data etc.
But to be honest with you i still don't get this all.

But at the moment i have project where i must do a lot of bitpacking and unpacking.

Can somebody point me to the tool or good tutorial that really clearly shows and explains these things?


For example i have a WORD and DWORD, every bit in this saves some info. Bits 0..1 hold one info, bits 2..7 another etc..
I can extract the data with SHR if i just shift right. For example if i need to know if bit 10 is 0 or 1 then i just do SHR 10 and i get that value.

But is there a more "cleaner" way? For me it's buggy. If i take one value then trying to get another from another place i get invalid or no data at all. I need some clear and sweet bitmasking to take "clean" values from data without bugs.

That's my problem. I really need good explanation or tutorial on this to finally understand this all and pack, mask and unpack data without problems.

I know Google has some. But you are the assembly and low level gurus here im sure you can recommend me something that helps me finally get working code.


Thanks a lot.

dedndave

if you want to know if bit 10 of EAX is set...

        test    eax,400h
        jnz     bit_10_is_set

there are also the BT (bit test) instructions, which are supoported on 386 or higher processors

http://www1.arl.wustl.edu/~lockwood/class/cs306/books/artofasm/Chapter_6/CH06-4.html#HEADING4-55

if you explain in more detail what you are trying to do, we can probably be more helpful  :bg

BytePtr

I need good tutorial and/or explanation on bit packing (unpacking).
I need to set values and toggle values for specific bits in BYTES, WORD or DWORDS.

For example i have one WORD value called MYDATA, every bit holds specific stuff in it:
Example table:

bits 0-9   tile graphic number (0-1023)      
bit 10   wall (1 = collide, 0 = no collide)      
bit 11   bullet wall (1 = collide, 0 = no collide)      
bit 12   flat (1 = flat, 0 = not flat)      
bit 13   flip (1 = flip, 0 = no flip )      
bit 14-15   rotation code (0=0°, 1=90°, 2=180°, 3=270°)   

Bits 0-9 can have integer values from 0-1023. Bit 10 can only be either 0 or 1 and so on, etc..

So i need help on how to toggle / modify each specific bit in (any data type, but usually just BYTE, WORD, DWORD).

I just don't have any luck toggling / modifying individual bits. That's why i ask some good tutorial or TUTORIAL TOOL (calculator) that really helps understanding this.

TIA.

donkey

"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

jj2007

First, for your own profit you need a tool for displaying registers bitwise. I use the Bin$(eax, f) function of MasmBasic, but the Masm32 dw2bin_ex also does the job.

include \masm32\MasmBasic\MasmBasic.inc

.code
start:
mov ebx, 10000000000b ; only bit 10 is set
Print "This is ebx as Bin$:", CrLf$, Bin$(ebx, f), CrLf$
test ebx, 10000000000b
.if !Zero? ; not zero means bit set
Print "Bit 10 was set", CrLf$
.else
Print "Bit 10 not set", CrLf$
.endif
inkey "Press any key"
Exit

end start


Output:
This is ebx as Bin$:
00000000000000000000010000000000
10987654321098765432109876543210
Bit 10 was set


Second, Olly is a must...
Third, \masm32\help\opcodes.chm contains essential info, see btst, xor, test
Fourth, trial and error ;-)

drizz

You can use masm RECORD feature for this rather than hard-coding offsets.

MYDATA RECORD \
rotation_code:2, \;bit 14-15   rotation code (0=0°, 1=90°, 2=180°, 3=270°)   
flip:1, \;bit 13   flip (1 = flip, 0 = no flip )
flat_:1, \;bit 12   flat (1 = flat, 0 = not flat)
bullet_wall:1, \;bit 11   bullet wall (1 = collide, 0 = no collide)
wall:1, \;bit 10   wall (1 = collide, 0 = no collide)
tile_graphic_number:10;(0-1023)
MYDATA_type typedef MYDATA;; == 16bits/WORD

someproc proc
LOCAL myd:MYDATA_type

movzx eax,myd

mov edx,eax
and edx,mask tile_graphic_number; edx=0-1023
;;shr edx,tile_graphic_number;; tile_graphic_number offset is 0 

;; READ rotation_code from eax
mov ecx,eax
and ecx,mask rotation_code
shr ecx,rotation_code; ecx=0-3
;; WRITE rotation_code to eax
mov ecx,ebx;rotcode
shl ecx,rotation_code
and ecx,mask rotation_code
or eax,ecx


.if eax & mask wall;check
and eax,not mask wall;------clear
or eax,mask wall;--------------set
.endif

.if eax & mask bullet_wall
.endif
.if eax & mask flat_
.endif
.if eax & mask flip
.endif




Use your debugger to see what code is generated.

The truth cannot be learned ... it can only be recognized.

dedndave

this probably is not exactly what you want
but, it should give you enough information to write the code you need

to construct a MYDATA word:

        mov     eax,RotationCode    ;start with 2-bit RotationCode (0=0°, 1=90°, 2=180°, 3=270°)

        shl     eax,1               ;make room for Flip
        or      eax,Flip            ;include Flip (1 = flip, 0 = no flip )

        shl     eax,1               ;make room for Flat
        or      eax,Flat            ;include Flat (1 = flat, 0 = not flat)

        shl     eax,1               ;make room for BulletWall
        or      eax,BulletWall      ;include BulletWall (1 = collide, 0 = no collide)

        shl     eax,1               ;make room for Wall
        or      eax,Wall            ;include Wall (1 = collide, 0 = no collide)

        shl     eax,10              ;make room for Tile
        or      eax,Tile            ;include Tile graphic number (0-1023)

        mov     MYDATA,ax           ;store MYDATA word

to de-construct a MYDATA word:

        movzx   edx,MYDATA          ;MOVZX sets the high word of EDX to 0

        mov     eax,edx
        and     eax,3FFh            ;bits 0-9 only
        mov     Tile,eax            ;store Tile graphic number (0-1023)

        shr     edx,10              ;bit 10 to bit 0
        mov     eax,edx
        and     eax,1               ;bit 0 only
        mov     Wall,eax            ;store Wall (1 = collide, 0 = no collide)

        shr     edx,1               ;bit 11 to bit 0
        mov     eax,edx
        and     eax,1               ;bit 0 only
        mov     BulletWall,eax      ;store BulletWall (1 = collide, 0 = no collide)

        shr     edx,1               ;bit 12 to bit 0
        mov     eax,edx
        and     eax,1               ;bit 0 only
        mov     Flat,eax            ;store Flat (1 = flat, 0 = not flat)

        shr     edx,1               ;bit 13 to bit 0
        mov     eax,edx
        and     eax,1               ;bit 0 only
        mov     Flip,eax            ;store Flip (1 = flip, 0 = no flip )

        shr     edx,1               ;bit 14 to bit 0
        mov     eax,edx
        and     eax,3               ;bit 0-1 only
        mov     RotationCode,eax    ;store RotationCode (0=0°, 1=90°, 2=180°, 3=270°)


BytePtr

Thanks a lot guys.
As always very helpful.  :thumbu

I will try them out.


This is must have knowledge for every programmer, i thought i never need this and didn't bothered to learn this.
And now here i am.

Sorry.

OK, dedndave:


Can you explain that thing:
You shl one value by 10 but value is actually in 11. I tried and your code works but why.

It has something to do with numbers going from 0..15 and not 1..16 in word?

donkey

Quote from: BytePtr on February 14, 2010, 06:31:18 PM
Can you explain that thing:
You shl one value by 10 but value is actually in 11. I tried and your code works but why.

It has something to do with numbers going from 0..15 and not 1..16 in word?

Yes, it is because we count from 0 so bit 11 is actually the 12th bit.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

dedndave

in the case of SHL EAX,10
the Tile value is 10 bits wide, so i shifted by 10 to make room for it at the lower end of the word (or dword)

easy to remember...
if you want to move a bit from bit 12 to bit 3, 12 - 3 = 9, you want to shift by 9 (right)

if you want to move a bit from bit 4 to 14, 14 - 4 = 10, you want to shift by 10 (left)

BytePtr

Thanks again.
I will make also few test apps just for education.
So i can play around with bits easily and without fear.

tenkey

Renaming some instructions might help:

AND - bit clear using complemented bit mask
The bit mask has 0-bits for each bit you want to be sure are 0.
The bit mask has 1-bits everywhere else.

1010 1101  ; packed data
1100 0001  ; Bit mask = 0C1h
1000 0001  ; (data AND bit-mask) bits 1-5 are cleared

AND (2nd interpretation) - keep bits using bit mask
The bit mask has 1-bits for each bit you want to keep.
The bit mask has 0-bits for all the other bits, which are set to 0.

1010 1101  ; packed data
0011 1110  ; Bit mask = 03Eh
0010 1100  ; (data AND bit-mask) bits 1-5 kept (extracted)

OR - bit set using bit mask
The bit mask has 1-bits for each bit you want to be sure are 1.
The bit mask has 0-bits everywhere else.

1010 1101  ; packed data
0010 1010  ; Bit mask = 02Ah
1010 1111  ; (data OR bit-mask) bits 1, 3, and 5 are set to 1

XOR - bit complement (toggle) using bit mask.
The bit mask has 1-bits for each bit you want to toggle.
The bit mask has 0-bits everywhere else.

1010 1101  ; packed data
0010 1010  ; Bit mask = 02Ah
1000 0111  ; (data OR bit-mask) bits 1, 3, and 5 are toggled

Extracting is clearing bits you don't want, and if desired or necessary, shifting the value into the correct position.

Insertion requires clearing out the destination field, shifting the value into position, then combining the two results with an OR or ADD. Because it is not a numeric operation, the preferred combining instruction is an OR.

Windows comes with a calculator that can do the AND, OR, XOR, and NOT operations. On XP and before, you need to set the calculator to Scientific view. On Win 7 (and presumably Vista),  there is a Programmer view.
A programming language is low level when its programs require attention to the irrelevant.
Alan Perlis, Epigram #8

GregL

Drizz beat me to it, use RECORD and MASK, it's pretty slick.


dedndave

i didn't know about those, Greg (and Drizz)
that does look pretty slick

oex

Quote from: dedndave on February 15, 2010, 05:27:39 AM
i didn't know about those

I dont believe you :lol

I didnt either leaving another open page to assimilate ::)
We are all of us insane, just to varying degrees and intelligently balanced through networking

http://www.hereford.tv