 Research / Megadrive Programming / Logical operations Before we start with logical operations, I will show some more Bcc instructions as I promised. Apart from data registers, address registers and program counter, there's an another register (last one, I promise) called SR (status register). We are now only interested in 5 bits of it, named CCR (flag register). Everything moved to CCR will be copied in the lower byte of SR (this works in reverse). Anyway, CCR consists of 5 bits, which are flags. These flags are set or cleared when certain thing is being done with registers, or an instruction is called. These flags are: - C Flag (carry) - 9th bit of adding, shifting and bit rotation. - V Flag (overflow) - It'll be set when result can't be represented. Eg. when you add \$01 (byte) to \$7F (byte), the result is \$80 and V flag will be set - Z Flag (zero) - Will be set when the result is zero. - N Flag (negative) - Will be set if the highest bit of result is set (in two complement it's the sign bit, so the signed negative) - X Flag (extended) - A copy of C flag. But what these things have to do with CMP and Bcc? In C, this code: something == 1 will return 1 if it's true. Now, when you compare two values, Z flag is set when they are the same or is cleared when they're different. BEQ branches if Z flag is set and BNE will branch if Z flag is cleared. So... BEQ and BNE can be used not only when comparing two values. Look at that example: ``` moveq #0,d0 beq zflagisset rts zflagisset:``` It will branch, because the result of setting d0 to 0 is 0 and Z flag is set. And BEQ branches if Z flag is set. This comes in handy if you want to test if a number is null or not. Here's a list of Bcc instructions: ```instr conditions flags required BEQ Branch if equal Z = 1 BNE Branch if not equal Z = 0 BGE Branch if greater or equal (signed) N = V BGT Branch if greater than (signed) N = V, Z=0 BLT Branch if lesser than (signed) N != V, Z=0 BLE Branch if lesser or equal (signed) N != V BHI Branch if higher than (unsigned) C = 0, Z = 0 BHS Branch if higher or same as (unsigned) C = 0 OR Z = 1 BLO Branch if lower than (unsigned) C = 1, Z = 0 BLS Branch if lower or same as C = 1 OR Z = 1 BCC Branch if carry clear C = 0 BCS Branch if carry set C = 1 BVC Branch if overflow clear V = 0 BVS Branch if overflow clear V = 1 BPL Branch if plus N = 0 BMI Branch if minus N = 1 BRA Branch Always = means equal, != means not equal =P``` Enough of these branches, let's learn about bits... I really hope you know what bits and bytes are. If you don't, a byte consists of 8 bits, which can be either 1 (set) or 0 (cleared). Number 7 is 111 binary. You can do fun stuff with bits. Eg. the keys pressed on joypad are all stored in one byte. Each bit of this byte represents a key: ```7 6 5 4 3 2 1 0 S A C B R L D U``` The lowest bit is up, bit 1 is down etc... Now if you want to know if B is pressed, what should you do? You should use the AND instruction. AND operation compares all bits of two values and sets a bit in a new one if this bit was set in both of the values. I'm not an expert of logical operations so you can laugh =P Example: ```Value 1: 10101100 Value 2: 11001010 -------- Result: 10001000``` Take a look at this code: ``` move.b (\$FFFFF604).w,d0 ;\$FFFFF604 is the joypad output in Sonic 1 and.b #\$10,d0 ;you could use #%00010000 beq Bnotpressed``` Imagine we press B, Up and Start. And instruction will look like that: ``` SACBRLDU Value 1: 10010001 (keys pressed) Value 2: 00010000 (and) -------- Result: 00010000``` The result is not zero so it won't branch! Nifty, isn't it? There are other: ` or.b #\$8,d0` OR sets the result bit if value 1 bit OR value 2 bit is set. ```Value 1: 00100100 Value 2: 00001000 -------- Result: 00101100``` Next: ` eor.b #\$24,d0` EOR sets the result bit if one and ONLY one bit is set in value bits (like x86 xor). ```Value 1: 00101110 Value 2: 00010100 -------- Result: 00111010 ``` And next: ` not.b d0` NOT clears the bit if it was set and sets the bit if it was cleared. (changes all bits) ```Before: 01001001 After: 10110110``` And now on with bit shifting. This operation moves bits by an ammount to the right or to the left. Eg. we'll shift a value 3 times to the right: ```Before: 00101000 After: >>>00101000``` So after this it'll be: ` 00000101` Bit shifting is fun because one shift to the left multiples a number by 2 and one shift to the right divides it by 2. The instructions: ``` lsl.b #3,d0 lsr.b #2,d1``` LSL shifts x bits to the left, LSR shifts x bits to the right. There's also bit rotating: ` rol.b #1,d0` It'll rotate a number one bit to the left: ```Before: 10101010 After: 10101010 |-------^ 01010101``` It works the same to the right. The last part of bits: ``` bset #1,d0 ;sets bit 1 of d0 bclr #2,d1 ;clears bit 2 of d1 bchg #3,d2 ;changes bit 3 of d2 (like not) btst #6,d0 ;test if bit 6 of d0 is set, sets ;z flag if it's cleared else clears z flag``` homework: ``` move.b #\$4,d0 or.b #\$1,d0 eor.b #\$2,d0 lsl.b #1,d0 ror.b #2,d0 btst #7,d0 bne branch rts branch:``` Now your homework is to guess if it is going to branch or not. Bit operations are boring at first but you'll get used to them... Back | Printer friendly<< 3. Compares, branches... | 5. Editing the game code >>