INTRODUCING 520ST ASSEMBLY LANGUAGE
MC 68000 tutorialby CHRIS CHABRIS
To a programmer, the most important feature of any computer is its "brain,"
the central processing unit (cpu). And the Atari 520ST sports the most
advanced cpu ever put into a personal computer-the 16-bit Motorola MC68000
microprocessor running at a clock speed of eight megahertz.
My first encounter with the 68000 occurred in a course on systems programming that I took last year at Harvard. Having learned machine language on the 6502 microchip in Atari's 8-bit computer line, I was pleasantly surprised. The 68000 instruction set seems like a high-level language, compared to the 6502.
Using a Macintosh computer, we constructed several large programs in 68000 assembly language, including an assembler, spreadsheet, and language interpreter. But then when I returned to an Atari l30XE, writing simple utilities seemed like using knives and bearskins to build a computer.
What is it about the 68000 that makes the trusty 6502 seem so crochety? Before we can answer that question, we must clarify what we mean when we say 68000.
In 1979 Motorola introduced a new family of general purpose microprocessors with the 68000 chip. (In the May, 1985 Antic, Meet the 68000 provides a basic description of the 68000 itself.) Although code written for the 68000 is compatible with all subsequent chips, there are some significant variations within the family:
- The 68008 is a version of the 68000 that addresses only one megabyte of memory and uses an 8-bit data bus. It transfers data, to and from memory, one byte at a time instead of two. This chip is used in the Sinclair QL computer.
- The 68010 has a few additional instructions, operates faster in certain loop situations and supports virtual memory Part of the address space is stored on external mass storage and "paged" in and out of main memory in order to simulate larger contiguous RAM than actually exists. This chip is used for running Unix in the AT&T 7300 PC.
- The 68020 is the true 32-bit version of the 68000, with data and address busses both 32 bits wide. It also supports the 68881 floating-point co-processor and many additional instructions. A so-called instruction cache holds the next intructions to be executed within the processor, so they do not have to be fetched from main memory each time
We can familiarize ourselves with the power of the 68000 by examining a simple program in excruciating detail. But if you have never seen 68000 assembly language before, there are a few things you need to know first.
Within the 68000 chip are eight general-purpose data registers-each 32 bits wide-labeled D0-D7. They can act like either the accumulator or the index registers in the 6502. There are seven 32-bit-wide address registers labeled A0-A6, and a 32-bit stack pointer labeled A7 or SP. The stack pointer points to an absolute address in the computer's memory, unlike the 6502 stack pointer which is an 8-bit offset to address $0100.
The 68000 instructions can operate on either a 8-bit byte, a 16-bit word, or a 32-bit longword. Bytes can be located at any address, but words and longwords must begin at even addresses. The size is denoted by affixing either a ".b", ".w", or ".l" to the instruction mnemonic, as in CLR.W D0, which would clear, or set to zero, only the first 16 bits of register D0.
Armed with this information, you should look at the listing in Figure 1. This is a short subroutine that computes the sum of the first N even natural numbers-or 2+4+...+N.
As the header comments indicate, the parameters are passed to and from the subroutine in the data registers.
; Compute the sum of the first N even natural numbers.
; N is passed in register D0. and register D1 will
; contain the intermediate and final results. Method:
; the first N numbers are Summed by counting down D0
; and adding its value into D1 until D0 reaches zero.
; Then D1 is multiplied by 2.
evensum: cir.1 D1
sumloop: add.1 D0,D1 ;Add current
;counter value to accumulator
subq #1,D0 ;Decrement
;counter by one
bne sumloop ;until it
mu1s #2,D1 ;Double sum to account
;for even numbers
D0 on entry contains the number of numbers to add, and Dl on exit will
contain the result. Note that the subroutine does no error checking. So
if the first N even natural numbers cannot be summed in a longword (the
maximum size of Dl), an incorrect result will be returned.
The program begins by clearing out register D1.l. (This notation references Dl as a longword. Dl.b, for example, would indicate the first eight bits of Dl.) Note that with the 6502, this 2-byte instruction could only be roughly simulated with well over 10 bytes of code!
Now the loop begins. In the loop, the program must add the value of register D0 to D1 and decrement D0 until it reaches zero, an algorithm which is executed by three instructions.
The first instruction adds D0 into Dl using the ADD instruction. Like most 68000 instructions, ADD takes two operands of any size: source and destination. Although both operands are data registers, in this case only one need be. Special variations on the ADD instruction-ABCD, ADDA, ADDI, ADDQ, and ADDX-take care of most other addressing situations and give the 68000 great arithmetic flexibility.
The SUBQ instruction is used next to decrement counter D0 by one. SUBQ is a special form of SUB. It only operates on longwords and subtracts an immediate value from 1 to 8 from the second operand. However, it is faster and more compact than the standard SUBI instruction, which can handle immediate operands of any size.
6502 hackers will find the familiar BNE instruction at the bottom of the loop, and it indeed acts just as its 6502 counterpart. It is one of a family of 15 branching instructions available on the 68000, each of which uses a word-size displacement. The address referenced in a branch instruction can occur up to approximately 32K bytes before or after the instruction itself.
The loop has ended, but one essential task remains. The accumulated sum must be doubled to account for the sum of the even numbers.
This is accomplished by the powerful MULS instruction, which here multiplies two by the value in Dl and stores the result in Dl. 6502 fans will note that the same thing can be accomplished on that chip with the ASL and ROL instructions. But what if we wanted to sum all the natural numbers counting by, say, 27? With the 68000, we just change the first MULS operand to 27. On the 6502 we would have to rewrite the loop, or code a complicated multiplication algorithm.
No subroutine is complete until it returns to its caller. Like the 6502, the 68000 does this with the RTS instruction. But unlike the 6502, the 68000 has different ways of getting to the subroutine in the first place: JSR (Jump to SubRoutine) and BSR (Branch to SubRoutine).
JSR operates on any address, and BSR operates on a 16-bit signed displacement-just like the branch instructions discussed earlier. No matter which instruction is used, control is returned with the same RTS instruction.
I hope this short program shows you how easy it is to program in 68000 assembly language, and how similar the 68000 actually is to the 6502. Although my article stressed the differences between the two chips, any dabbler in 6502 assembly language will have no trouble learning the intricacies of the 68000.
Chris Chabris used to be a very active writer for Antic, but this is the first article he's had time to work on since entering Harvard University as a computer science major last fall.
M68000 16/32-bit Microprocessor Programmer's Reference Manual
Motorola Data Sheets:
Programming the M68000
by Tim King and Brian Knight
The Motorola MC68000 Microprocessor Family
by Thomas L. Harman and Barbara Lawson.
Englewood Cliffs, NJ
68000 Assembly Language Programming
by Kane, Hawkins, and Levanthal
The 68000: Principles and Programming
by Leo J. Scanlon
Howard W Sams & Co., 1984