![]() |
|||||||||||||||
|
ASM Programming for the Sega Megadrive - Chapter 1 | . |
The Sega Megadrive gaming machine consists of the following: a cartridge port, where ROM images on a cartridge are placed; two controller ports, where controllers are plugged in; a power socket, which is used by a power transformer to carry electricity into the Megadrive; an AV socket which is used by the Megadrive to transfer video data to the TV/monitor via an RGB cable; an expansion port, technically, a second cartridge port, used by hardware expansions such as the Sega MegaCD; a Motorola 68000 processor, used by the Megadrive for most of the main computing; a Z80 processor, mainly used to process all of the sound code; a Video Display Processor, used by the M68000 to manage all of the video hardware; memory, used by the many different parts of the Megadrive's hardware; a motherboard, used to connect all hardware to the processor. During the course of this tutorial, we will learn about many of the different aspects of each hardware feature mentioned above.
Sega Megadrive games or educational software are stored on a cartridge in the form of a ROM image. The word ROM is short for Read Only Memory and, as the name suggests, can be read from only. A cartridge consists of a circuit board containing a ROM chip among other small and usually insignificant components. When the Megadrive is turned on, one of the first tasks it performs is checking the cartridge port to see if a cartridge is present. If the cartridge is missing, then all processing is stopped and a blank screen is displayed. Otherwise, the following writing is displayed onto the screen, "Produced by, or under licence from Sega Enterprises Ltd.". The Megadrive's operating system then passes control to ROM image contained on the cartridge present in the cartridge port.
A Megadrive ROM consists of the following: a header present at the start of the ROM, which is checked by the Megadrive's operating system to verify that the cartridge is genuine; instructions for the M68000 processor to process. Each instruction contained on a Megadrive ROM is 16 bits in size. This is why the Sega Megadrive is referred to as being a 16 bit machine. A typical instruction might look this: 1100000000010100. Such instructions tell the M68000 to do such things as adding numbers, or moving data into different memory addresses. Instructions can also be called mnemonics.
As mentioned above, the Megadrive uses three different processors that perform different tasks. The main processor that executes all instructions contained in a ROM is the Motorola 68000. The other two processors, the Z80 for the sound hardware, and the Video Display Processor for all video hardware, are controlled using the M68000 processor.
Each processor contains many internal memory locations called registers. Accessing internal registers is much faster than accessing the main memory (so fast in fact, that it is equivalent to comparing a snail to a jet-plane!), and so, a good programmer would avoid using main memory and use processor registers instead. A processor also contains a system bus, used to read from and write to external memory and other hardware devices.
Memory is a device made up from multiple electronic components called chips. A chip contains binary data. Unlike a ROM, chips used for memory are re-writable. This means that instead of only being able to read the data contained, we can also change and even erase it. Memory is used by the Megadrive to read from and control all of the Megadrive's hardware. Without memory, programming would be impossible. Memory is also called RAM (Random Access Memory), so called because memory can be read from and written to from any location. For example, a ROM (which is copied from the cartridge into main memory as it is run) at the beginning of the main memory can read data stored in user memory (which is located at the end of the main RAM).
The Motorola 68000 Processor
As written above, the M68000 processor, supplied by Motorola, is the centre of all operations for the Megadrive. There is also a Z80 processor which controls all of the sound hardware, and a Video Display Processor used to control all of the video hardware. These two processors are controlled by the M68000. Processors are also sometimes called CPUs, chipsets or architectures.
Processors are made almost entirely from electronic devices called transistors. A transistor is a very tiny switch, which is toggled by sending a voltage through it. So practically, a processor is a large set of very tiny switches; the code we write toggles some of these switches. The M68000 is called so, because it contains 68000 transistors.
A processor contains the following: an arithmetic logic unit, or ALU for short and control unit, or CU for short. The ALU is is the part of the processor that executes all arithmetic instructions, whilst the CU executes all instructions which alter the natural flow of a program. As well as the ALU and CU, a processor also contains many internal registers. Registers are small memory blocks, inside of the CPU, which can be used very quickly; much faster that main memory. Although a processor contains many registers, the programmer is only permitted to use a small amount of them. Inside the M68000, we are permitted to use the following registers: a0, a1, a2, a3, a4, a5, a6, a7, d0, d1, d2, d3, d4, d5, d6, d7, PC and SR.
Registers a0-a6 are called address registers. They are used to point to locations in main memory, making reading and writing to main memory much faster. They can each contain up to 32 bits or one longword.
Registers d0-d7 are called data registers. They are used to store data in, whilst a function is being carried out. These can also contain up to 32 bits.
SR stands for Status Register, and is used to mark the outcome of certain arithmetic operation. Bits (also called flags) are set to mark different results of logical instructions, and are then read by conditional branch instructions.
Register a7 is called the stack pointer. It is used to move and retrieve data to and from the stack. A stack is a register used to store information from registers temporarily so that it can be retrieved later.
The Program Counter or PC is used to store the address of the next instruction to be executed. The PC can be altered using branch or jump instructions.
Resets, Interrupts and the Operating System ROM
The Megadrive uses two different methods of reset: hard reset and soft reset.
With a hard reset, the power supply is stopped and all data contained in main memory and internal registers is lost. When power is returned to the Megadrive, the Operating System ROM is executed before the cartridge ROM is executed. A hard reset can be enabled by toggling the main switch on the front of a Megadrive.
During a soft reset, only the M68000 processor is reset. All data in it's registers is lost, including the Program Counter. This means that the whole of the cartridge ROM is re-executed. The Operating System is bypassed. A soft reset can be enabled by pressing the 'reset' button on the front of a Megadrive.
On power on, before any code contained on the cartridge ROM is executed, the Megadrive executes an internal Operating System ROM. The Operating System ROM reads from the cartridge port and the extension port to determine whether or not there is a genuine Megadrive program present. If a genuine ROM is present in the cartridge or extension port, then a message is displayed on the screen and control is passed to the program contained on the ROM. If however, a ROM is not present, or the program is unauthorised, then a blank screen is displayed and the Megadrive stops running.
Binary Notation
However obvious it may be, it must be pointed out that processors and computer systems do not store and deal with numbers or data in the way the reader would, that is, using the decimal number system. Because of the nature of the components that make up a processor, numbers are represented using the binary number system. In binary, each digit can have one of two values: either an on value, or an off value. In actual hardware, an on value is represented by sending a medium voltage (usually 5 volts) down a cable, whilst an off value is represented by sending a very small voltage (usually 0.05 volts). However, in diagrams and Assembly Language, an on value is represented as a '1' and an off value is represented as a '0'. Binary digits are often called bits.
Converting from Decimal into Binary
Converting decimal numbers into binary is very simple. To convert from decimal to binary, one just divides the decimal number by two (since binary can have one of two values); the residue of this sum will either be a '1' or a '0' this is the right most digit of our binary number. To work out the next digit, one would simply divide the answer to the first sum by two and note the residue.
Example, decimal number 67 into binary:
67/2= 33 r1 1 33/2= 16 r1 11 16/2= 8 r0 011 8/2= 4 r0 0011 4/2= 2 r0 00011 2/2= 1 r0 000011 1/2= 0 r1 1000011Our binary number 47 is only 7 bits in size. Since there are 8 bits to a byte, one would put an additional zero as the left most digit. Our binary number is 01000011.
Example, decimal number 45 into binary:
45/2= 22 r1 1 22/2= 11 r0 01 11/2= 5 r1 101 5/2= 2 r1 1101 2/2= 1 r0 01101 1/2= 0 r1 101101Again, this binary number is only 6 bits in size, so to make it one byte, one would add two zeros as the left most digits.
Example, decimal number 9 into binary:
9/2= 4 r1 1 4/2= 2 r0 01 2/2= 1 r0 001 1/2= 0 r1 1001This number is only 4 bits (also called a Nybble) in size. One would need to make it a byte in order to use it. So, one just adds four zeros as the left most digits.
Converting from Binary into Decimal
Often, one would have the need to convert a binary number into a decimal number, especially when programming hardware. Converting from binary into decimal is also very simple. For this one would use a positional value formula, that is, one would multiply the binary digit, either '1' or '0', with two (binary digits can have one of two values) indexed with it's position.
Example, binary number 10011011 into decimal:
1*2^0= 1 1*2^1= 2 0*2^2= 0 1*2^3= 8 1*2^4= 16 0*2^5= 0 0*2^6= 0 1*2^7= 128 1+2+0+8+16+0+0+128= 155The theory behind basic mathematics is beyond the scope of this tutorial, however the reason for using the above formula will be explained. The first number in each sum is always a '1' or a '0'. These are the two possible values of a single binary digit. The number is then multiplied with 2 indexed by it's position. In binary the right most digit, if on, will have the value of one. The next digit to the right, if on, holds the value of 2. Each positional value is the positional value of the right, doubled. More practically, each positional value is equal to two indexed with it's position from the right. For example the fifth digit from the right, if on, will hold the value of 16, which is 1*2^8. Note that each positional value starts at 0 since, 1*2^0= 1. This means that the fifth positional value is actually 4.
Example, binary number 10101111 into decimal:
1*2^0= 1 1*2^1= 2 1*2^2= 4 1*2^3= 8 0*2^4= 0 1*2^5= 32 0*2^6= 0 0*2^7= 128 1+2+4+8+0+32+0+128= 175
Example, binary number 00001110 into decimal:
0*2^0= 0 1*2^1= 2 1*2^2= 4 1*2^3= 8 0*2^4= 0 0*2^5= 0 0*2^6= 0 0*2^7= 0 0+2+4+8+0+0+0+0= 14Using the above formula, converting from binary in to decimal is a very simple process. In the perfect situation, the programmer would have a program or calculator which could be used to convert from binary in to decimal and from decimal in to binary.
Hexadecimal Notation
Converting from hexadecimal in to decimal and from decimal in to hexadecimal is not as simple as converting from, and to binary. For this reason, no algorithms will be explained. Instead, the basic concept of hexadecimal notation will be explained.
Using decimal notation, one could count from zero to nine before running out of digits. When this happens, one would simply increment the digit to the left and then count from zero to nine again. Using decimal notation, one could count from zero to nine and then from A to F before running out of digits, in which case one would increment the digit to the left and then count from zero to nine and then from A to F again.
0123456789 0123456789ABCDEFHexadecimal notation is much more efficient than decimal for programmers to use, since one byte (that is, 8 bits or binary digits) can be represented using only two digits instead of 3.
When converting from binary into hexadecimal, it is very efficient to split the binary number into separate numbers, each four bits in size. One then converts the four bit decimal number into decimal, and then into hexadecimal.
Example, 11101101 into hexadecimal:
1110 1101 1110 = 0*2^0= 0 1*2^1= 2 1*2^2= 4 1*2^3= 8 0+2+4+8= 14 In hexadecimal: E 1101 = 1*2^1= 1 0*2^2= 0 1*2^3= 4 1*2^4= 8 1+0+4+8= 13 In hexadecimal: D 11101101 = ED
Data Sizes
Before learning about machine code and assembly language, it is important that the reader understands all of the units with which data is measured and used.
Bit - one binary digit.
Byte - 8 binary digits, 2 nybbles.
Nybble - 4 binary digits, half of a byte.
Word - the size of each machine code instruction. A word on the Megadrive is 16 bits, or 2 bytes.
Longword - 2 words, 4 bytes, 32 bits.
When each measurement of data is grouped in one thousand and twenty fours, it's name is prefixed with 'kilo', for example, kilobyte is one thousand bytes. 'mega' is prefixed to the name of the measurement to measure groups of one million forty eight thousand five hundred and seventy six.
It is hoped that the reader now has a very basic understanding of the inner workings of the Sega Megadrive home console gaming machine. It is important to understand that not every aspect of the Megadrive has been explained. This is left to many of the other Megadrive technical resources that can be found on the internet.