News
Documents
Source Code
Downloads
Message Board


Sega Megadrive Assembly Programming Basics

Copyright, Lewis Bassett, December 2005


Chapter 4 - Assembly Language

Section 3 - Logical Instructions

Logical instructions work on a bit level, meaning they compare and change seperate bits. They are used to make up very important parts of Sega games, and it's really important to understand how to use them.

Logical instructions work with a special part of the processor called the Condition Code Register, or CCR for short. The CCR records the outcome of certian instructions using flags, so that other instructions can use them to make decisions.

Flags are represented with one bit, and can be either 'on' or 'off'. The M68000 uses five flags, to cover five different possible events: Carry, Overflow, Zero, Negative and Extent, represented by some documents as: 'C', 'V', 'Z', 'N' and 'X'.

The Carry flag is set whenever a number becomes too big to fit into a register, usually after an ADD instruction. This flag acts as an extra bit for the number temporarily to give the program a chance to fix the problem. So for example, a register can hold up to 32 bits. If (after an addition) the number suddenly becomes a 33-bit number, the Carry flag is set.

The Overflow flag works like the Carry flag, except it is set after a signed number becomes too large.

The Zero flag is set whenever the result of an instruction is zero.

The Negative flag is set on signed numbers only, when the result of an instruction is less than zero.

The last flag, Extend is usually unaffected. It is only ever set when the Carry flag is set.

The different flags described above are set using the logical instructions described in this section.


Not

The NOT instruction is used to invert all the bits of a number. For example, the number '00001000' (8) becomes '11110111' (247). You'll notice, everywhere a '1' used to appear, a '0' has replaced it, and vica versa.

The not instruction is a single operand instruction, which means it can only work with a data register. Memory addresses or address registers will not work.

	move.b	#$99,	d0;
	not	d0;
The number $99 is copied into register d0, which is then inverted to $66.

NOT instructions do not set any flags.


And

The AND instructions work with two different numbers, the source and the destination. The result is stored in the destination. Basically, an AND instruction takes the most significant bit from both numbers, and if they are both '1', it sets the result as '1'. It then moves on to the next bit.

	Number 1:	11001110
	Number 2:	11101001
	Result:	11001000
The AND instruction takes the first bits from each number: '1' and '1'. Since they are both '1', the result is set to '1'. The next bits from each number are also '1' and '1', so the result is '1'. Moving along, the next two bits are '0' and '1'. Since only one of them is '1' and not both, the result is set to '0'. They next two bits are '0' and '0'. None of them are '1', so the result is '0'. You get the general idea. If not read over again.

Here's some code:

	move.b	#$ce,	d0;
	move.b	#$e9,	d1;
	and.b	d0,	d1;
$ce and $e9 are copied into d0 and d1. Both registers are then ANDed and the result is stored in register d1, which now holds the value $c8.

AND instructions set the Negative or Zero flags, according the result of the operation.


Andi

The AND instruction requires that the destination operand is a data register. The source can be a memory address or data register. Immediate data does not work. For this we use the ANDI instruction. ANDI (AND Immediate) works with an immediate number as the source operand. The destination operand must still be a data register.

	move.b	#$ce,	d0;
	andi.b	#$e9,	d0;
This code copies $ce into register d0, which is then ANDed with the value $e9. The result is stored into d0.

Notice how the AND instruction also requires the programmer to specifiy if the instruction works with a byte, word or longword.

AND instructions are typically used to discard unwanted information. What do I mean by this? Say I have an 8-bit number, but I'm only interested in the most significant four digits. I would AND the 8-bit number with a mask, with the bits set, that I want to save: %11110000.

	move.b	#$46,		d0;
	andi.b	#%11110000,	d0;
Notice how I'm using a binary number as the immediate value. You may recall that in assembly, binary numbers are represented by preceding the number with a '%'. The left four bits are set, as these are the bits we want to keep. The other bits, regardless of whether they are '1' or '0' will return '0', since an AND instruction requires both bits to be set. The right four unwanted bits are now lost, but the left four are kept exactly the same as they were. This technique will come in very usefull later.

Just like the AND instruction, ANDI also sets the Negative or Zero flags, according to the result of the operation.


Or

The OR instruction works in a similar way to the AND instruction. AND instructions require both bits from each number to be set, the OR instruction will set the result bit if either of the bits from the first number or the second number are set. Take these two numbers:

	Number 1:	11010101
	Number 2:	10001011	
	Result:	11011111
The first bits from Number 1 and Number 2 are '1' and '1', so the result bit is '1'. The next bits for Number 1 and Number 2 are '1' and '0'. Because at least one of the bits is '1', the result bit is set to '1'. However, because the next bits for both numbers are both '0', the result bit is set to '0'. You get the idea.

The OR instruction also requires the processor to specify whether the instruction uses 32-bits, 16-bits or 8-bits.

	move.b	#$d5,	d0;
	move.b	#$8b,	d1;
	or.b	d0,	d1;
$d5 and $8b and moved into registers d0 and d1, then ORed with the result stored in register d1.

OR instructions sets either the Zero or Negative flag after an operation.


Ori

Just like the AND instruction, OR cannot use immediate data. To do this, we must use the ORI instruction.

	move.b	#$ff,		d0;
	ori.b	#%10100001,	d0;
The value $ff is moved into register d0, which is then ORed with the binary number %10100000. The result is stored in register d0.

ORI instructions also reset the Zero or Negative flags after each operation.


Eor

EOR is short for Exclusive OR and is the last logical instruction that I will cover. This instructions works just like AND and OR, except that it will only set the result bit to '1' if only one of the bits is '1'. If both bits are '1', then EOR will set the result as '0'. If both bits are '0', then the result bit will also be set as '0'. Consider these two numbers:

	Number 1:	11001110
	Number 2:	10010101
	Result:	01011011
The first bits from Number 1 and Number 2 are '1' and '1'. Because both of them are '1', and not just 1, the result is set to '0'. The next bits along for Number 1 and Number 2 are '1' and '0'. Since only one bit is '1', the result is set to '1'. The next bits are '0' and '0'. Since none of them are '1', the result bit is set to '0'. You get the general idea.

EOR instructions also require the programmer to specify if the instruction is to work with a byte, word or longword. EOR instructions require that the destination is always a data register. The source operand can be a data register or memory location.

	move.b	#$ce,	d0;
	move.b	#$95,	d1;
	eor.b	d1,	d0;
Here, the value $ce is copied into register d0 and $95 into register d1. Both registers are then EORed and the result is stored in register d0.

After each EOR instruction, the Negative or Zero flag is set according to the result.


EORI

As I explained, the EOR instruction cannot work with immediate data. Using immediate data is slow, but sometimes it's the only way. To work with immediate data, we use the EORI instruction. The destination operand must be a data register.

	move.b	#$ce,	d0;
	eori.b	#$95,	d0;
The value $ce is copied into register d0, and then EORed with the immediate value $95. The result is stored in register d0.

EORI instructions, just like all the other logical instructions, set the Zero or Negative flag, according to the result of the operation.

I've explained all the logical instructions as basically as I can. It may help to give this section a re-read if something's still not clear to you, before moving onto Section 4, where I explain comparing and testing.



Chapter 4 - Section 2 Contents Chapter 4 - Section 4


Designed & maintained by Lewis AS Bassett
SEGA, Megadrive, Genesis, Sonic the Hedgehog, etc are all owned by Sega Enterprises Ltd