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 >>

© 2004, 2005 drx, www.hacking-cult.org. Don't copy without permission yadda yadda yadda.