Day 16 - Bit Masking/Toggling




Masking


	Today, we'll get right to the point. Masking, as in clearing certain bits
while leaving the others intact. This is done (atleast alot of the time) with the
AND instruction. The syntax is like this:

	and (CPUregister),(CPUregister),(number or register)

Say we want to clear the last 16bits of the register, but leave the others intact.
Assuming r3 was the register we're using:

	and r3,r3,0xFFFF0000

Remember ANDing a bit with 1 will give the same value that you started with, and
ANDing with 0 will always have an answer of 0, since the AND logic table is like 
this:

		AND Table
	-----------------------------
	Start  | ANDed with | Result
	-----------------------------
          0    |     1      |   0
	  0    |     0      |   0
	  1    |     0      |   0
	  1    |     1      |   1

It's OK if you already knew that, the tables today are for the people who are
going to have to figure out all this bit logic stuff (ANDs, ORs, XORs, NOTs) on
their own because they haven't used ASM before encountering the GBA.

	Alright, now your probably wondering (maybe) how hex maps out to binary.
(HEX to BINARY conversion). Here's a table of hex digits:

		Hex 2 Binary
	---------------------------------
		0	|    0000
		1	|    0001
		2	|    0010
		3	|    0011
		4	|    0100
		5	|    0101
		6	|    0110
		7	|    0111
		8	|    1000
		9	|    1001
		A	|    1010
		B	|    1011
		C	|    1100
		D	|    1101
		E	|    1110
		F	|    1111

So now you know (if you couldn't already) how to convert each hex digit to binary.
So 0x0000FFFF becomes %00000000000000001111111111111111 . The percent is the symbol
Goldroad uses for binary numbers.

	Now what if you only want to mask certain bits out (to 0). You might want
to do the AND instruction in binary. What ever bits you make 0 will be 0 when the
AND is complete, and whatever bits are 1 will make the corresponding bit in the
CPU register stay the same (wether it be 1 or 0). Example:

	;we want to make bits #3 and #15 clear (0). Remember to count bits
	; from #0 on far right.
	and r3,r3,%11111111111111110111111111110111

Note the underlined '0's, the corresponding bits in r3 will be '0's, but everything
else will remain unchanged.

	Now, what if we wanted to mask bits to be set (change to a 1). Then we would
have to use OR. Take a look at the OR table below:

		OR Table
	-----------------------------
	Start  | ORed with | Result
	-----------------------------
          0    |     1      |   1
	  0    |     0      |   0
	  1    |     0      |   1
	  1    |     1      |   1

You should see that AND's result is 1 if BOTH inputs are 1. OR's result is 1, if one or
both inputs are 1.

	To set individual bits to 1 (I don't actually know why you'd want to do this, but
the method I tell DOES work), you just OR with 1. The bits you don't want to change,
you OR with 0. So to set bits #6 and #14 of r3 to 1 , we would go like this:

	orr r3,r3,%00000000000000000100000001000000

Note that the instruction for OR is ORR, I guess it's like semi-traditional to have
3 letter ASM instructions. I hope you understood that, we OR the bits we want set to
1 with 1 and the bits we want to leave alone with 0.

Also note that the GBA is a 32bit system so we need all 32bits in our binary numbers.
If you don't put all 32bits in, I think Goldroad will interpret it as having 0's on
the left as in being the number you think it'll be, but I'm not sure about this, you
might need all 32bits.

Toggling

First of all, let's define toggling. Toggling is switching between 0 and 1. The method shown here is useful for toggling bits on (1) and off (0) with one instruction if you execute that instruction repeatedly. The easiest type of toggling is just switching all the bits in a register. This is easily done with a MVN instruction. The syntax of MVN is like so: MVN (CPUregister),(CPUregister) All the bits in the second register will switch (1 to 0 or 0 to 1) and then the result will be stuck in the first register. So if you just wanted to switch all the bits of r3, you would do: mvn r3,r3 Simple! MVN stands for (MoVe Negated or MoVe Not). NOT is a bit operation like OR and AND but only takes one input, here's a table: NOT Table --------------- Start | Result --------------- 0 | 1 1 | 0 NOT is simple, no? However, sometimes you want to toggle just individual bits, not all of them. For this kind of toggling, you need the XOR. Here's a table for XOR: XOR Table ----------------------------- Start | XORed with | Result ----------------------------- 0 | 1 | 1 0 | 0 | 0 1 | 0 | 1 1 | 1 | 0 XOR only results in 1 if one (not both) of the inputs is 1. So XORing with a 1 will toggle the bit. The syntax of XOR is: eor (CPUregister),(CPUregister),(number or register) Note that the instruction for XOR is EOR. The thing is that they both stand for (Exclusive OR (EOR)) or XOR (eXclusive OR). So if we wanted to toggle bits #1 and #20: eor r3,r3,%00000000000010000000000000000010 XORing with 0 will make the bit stay the same, but XORing with 1 will make the bit opposite of what it is.

A Few Things To Remember

Just a quick note here about toggling. Alot of times, you will have a define that... well, defines the bit/bits you want to toggle. And you can toggle more than one bit at a time separating the bits with the pipe '|' symbol like so: eor r3,r3,SIZE_DOUBLE | MOSAIC ; toggle the SIZE_DOUBLE and MOSAIC sprite things assuming ; r3 contains the OAM attribute that you want to toggle those ; in. Hope this isn't too hard.

Day In Review

I seriously hope you learned something today. Toggling and Masking bits is fun! Have fun! Happy coding!, -Mike H a.k.a GbaGuy
Intro - Day 17

Patater GBAGuy Mirror
Contact