MC 68000 ASSEMBLY LANGUAGE COURSE PART VIII by Mark van den Boer
Welcome back! First I've got to apologize to everyone who missed
a part of this course in the last issue of ST NEWS. Due to lack
of time (read: more urgent things to do), I wasn't able to send
part 8 before the deadline.
Program Control Instructions
This class of instructions enables a programmer to create loops
and IF-THEN-ELSE like decisions. That's why it's the most
important group of instructions and every programmer should have
a thorough knowledge of this group. This class of instructions
are specifically meant to affect the program counter.
Instructions: Bcc (cc stands for Condition Code)
Syntax: Bcc <address>
Data sizes: Byte or word. This implicates that the branch-
instructions can branch in an area of 32K. When
using a branch with a byte offset you can put a .S
suffix behind the instruction e.g. BEQ.S . When
using a branch with a word offset you can put a .W
suffix behind the instruction e.g. BEQ.W . Most
assemblers will determine if the short or word
form is needed. Also most assemblers will optimize
word-branches to byte-branches whenever possible.
Condition codes affected:
None
Function: Test a combination of the NZVC-flags in the status-
register and conditionally perform a branch to another
address. If the testing of the condition codes is true,
then the branch will be taken, in the other the
instruction immediately following the Bcc instruction
will be executed. A total of 15 possible variations of
this instruction are listed below.
BCC: where CC stands for Carry Clear. The branch is
taken if the C-bit is 0. This instruction is often
used in combination with shift and rotate
instructions.
BCS: where CS stands for Carry Set. The branch is taken
if the C-bit is 1. This instruction is the
counterpart of the BCC-instruction.
BEQ: where EQ stand for EQual. The branch is taken if
the Z-bit is 1. This instruction is often used
after a TST-instruction or CMP-instruction.
BNE: where NE stands for Not Equal. The branch is taken
if the Z-bit is 0. This instruction is the
counterpart of the BNE-instruction.
BPL: where PL stands for PLus. The branch is taken if
the N-bit is 0. This instruction is often used
after a TST-instruction or CMP-instruction.
BMI: where MI stands for MInus. The branch is taken if
the N-bit is 1. This instruction is the
counterpart of the BPL-instruction.
BVC: where VC stands for oVerflow Clear. The branch is
taken if the V-bit is 0. This instruction is often
used after an Integer Arithmetic instruction like
ADD, SUB, MUL etc.
BVS: where VS stands for oVerflow Set. The branch is
taken if the V-bit is 1. This instruction is the
counterpart of the BVC-instruction.
BRA: where RA stands for bRanch Always. This
instruction is often used at the end of a loop to
go back to the beginning of the loop.
Branches often used after an arithmetic operation on
two's complement numbers.
BGE: where GE stands for Greater or Equal. This branch
is taken if the N and V-bits contain the same
value.
BGT: where GT stands for Greater Than. This branch is
taken in the following cases:
- N is 1, V is 1, Z is 0
- N is V is Z is 0
BLE: where LE stands for Lower or Equal. This branch is
taken in the following cases:
- Z is 1
- N and V-bits contain different values
BLT: where LT stands for Less Than. This branch is
taken if the N and V-bits contain different
values.
Brances often used after an arithmetic operation on
unsigned numbers.
BHI: where HI stands for HIgher. This branch is taken
if the N and V-bits contain the same value.
BLS: where LS stands for Lower or Same. This branch is
taken if the C and Z-bits contain different
values.
Example:
This shows a piece of a C-program and an equivalent
piece of a PASCAL-program which are translated into
assembler. (variabele is signed)
C:
if (variable == 1 || variable > 4) variable = 5;
else var *= 3;
PASCAL:
if (variable == 1) or (variable > 4)
then variable := 5
else variable := variable * 3
* Most assemblers will optimize the branch-instructions
* to the short forms
CMP.W #1,variable
BEQ L10000
CMP.W #4,variable
BLE L2
L10000:
MOVE.W #5,variable
BRA L3
L2:
MOVE.W variable,R0
MULS #3,R0
MOVE.W R0,variable
L3:
Instructions: DBcc (cc stands for Condition Code)
Syntax: DBcc Dn,<address>
Data sizes: byte or word. This implicates that the branch-
instructions can branch in an area of 32K. Dn is
considered to contain a word.
Condition codes affected:
None
Function:
The group of Decrement and Branch (DBcc) instructions
provide an efficient way of creating loops. They are
nearly always placed at the end of a loop. First the
condition is tested, then the dataregister is
decremented. The branch is taken in the following
cases:
- Dn is -1;
- The condition cc in DBcc is satisfied.
There are 16 possible variations of this instruction.
They all are nearly the same as the Bcc-instructions,
with two exceptions. These are:
DBF or DBRA:
This loop can only be terminated by count since
the other condition can never be satisfied.
DBT: Only performs a decrement on the dataregister and
never branches. To me this seems a pretty useless
instruction, which is only there to make the DBcc
series logically complete.
Example:
This piece of code is an efficient implementation of
the strcpy-function of the C-language. A0 contains the
address of the source string and A1 contains the
address of the destination string. In C the end of a
string is marked by a byte containing 0.
MOVE.W #$ffff,D0
LOOP: MOVE.B (A0)+,(A1)+
DBEQ D0,LOOP
This piece of code can easily be transformed into the
strncpy-function by loading D0 with the appropriate
value.
Instructions: Scc (cc stands for Condition Code)
Syntax: Scc <address>
Data sizes: byte.
Condition codes affected:
None
Function: Sets a byte to $ff if the condition codes satisfie. If
the condition is not satisfied the byte is set to 0.
This group of 16 instructions is rarely used. Nearly
all forms are the same as the DBcc group except for the
following two instructions:
SF: the same as a CLR.B instruction
ST: the same as a MOVE.B #$ff, <address>
Example:
Be inventive, invent one yourself!
Instruction: BSR, JSR
Syntax: BSR <address>
JSR <address>
Data sizes: none
Condition codes affected:
none
Addressing modes allowed (only for JSR):
Destination:
(An)
w(An)
b(An,Rn)
w
l
w(PC)
b(PC,Rn)
Function: The BSR (Branch to SubRoutine) and JSR (Jump to
SubRoutine) instructions are used for calling
subroutines. BSR can branch in a range of 32K. JSR
should be used when a jump out of the 32K range is
needed. Some assemblers optimize JSR into BSR
instructions whenever possible, since BSR is more
efficient than JSR. When executing a BSR/JSR
instruction, the 68000 first pushes the PC (program-
counter) on the stack and then load the PC with the new
address. See below for the RTS (ReTurn from Subroutine)
instruction.
Instruction: RTS
Syntax: RTS
Data sizes: none
Condition codes affected:
none
Function: Counterpart of BSR/JSR instructions. Reloads the PC
with the value on top of the stack. This value will
nearly always have been put on top of the stack by a
BSR/JSR instruction.
Example: * the strcpy function discussed before
STRCPY:
MOVE.W #$FFFF,D0
LOOP: MOVE.W (A0)+,(A1)+
DBEQ D0, LOOP
RTS
* some other code
BEGIN:
MOVE.L #SOURCE,A0
MOVE.L #DEST,A1
JSR STRCPY
RTS
* the strings are put in a data area
.DATA
* 80 bytes for every string
SOURCE .DS.B 80
DEST .DS.B 80
* .DS.B means Define Storage Byte
* so 80 bytes are define as storage for each string
Instruction: JMP
Syntax: JMP <ea>
Data sizes: none
Condition codes affected:
none
Addressing modes allowed:
Destination:
(An)
w(An)
b(An,Rn)
w
l
w(PC)
b(PC,Rn)
Function: Transfer program control to another address. The PC is
loaded with the specified address. In fact this is a
variant of the MOVE instruction. In this case the
destination register is inherently defined, namely the
PC-register. Therefore we could translate JMP <ea> to
MOVE.L <ea>,PC .
Instruction: RTR
Syntax: RTR
Data sizes: none
Condition codes affected:
none
Function: ReTurn and Restore. Counterpart of BSR/JSR
instructions. Reloads the PC with the value on top of
the stack. This value will nearly always have been put
on top of the stack by a BSR/JSR instruction. The only
difference with the RTS is that with this instruction
also the CCR is reloaded. This instruction is rarely
used but comes in handy when one doesn't want a
subroutine to influence the condition codes. Before the
JSR instruction you should use the instruction:
MOVE.B CCR,-(A7)
which pushes the CCR on the stack
Next time: The last part of the instruction set. These are the
instructions which can only be executed when supervisor-mode is
active.
Disclaimer
The text of the articles is identical to the originals like they appeared
in old ST NEWS issues. Please take into consideration that the author(s)
was (were) a lot younger and less responsible back then. So bad jokes,
bad English, youthful arrogance, insults, bravura, over-crediting and
tastelessness should be taken with at least a grain of salt. Any contact
and/or payment information, as well as deadlines/release dates of any
kind should be regarded as outdated. Due to the fact that these pages are
not actually contained in an Atari executable here, references to scroll
texts, featured demo screens and hidden articles may also be irrelevant.