Dec 052017
Motorola M6800 emulator and cross assembler.
File 68EM.ZIP from The Programmer’s Corner in
Category Assembly Language
Motorola M6800 emulator and cross assembler.
File Name File Size Zip Size Zip Type
68EM.COM 13091 6433 deflated
68EM.ICO 766 248 deflated
68EM.PIF 545 147 deflated
68EM.TXT 47533 15193 deflated
68EMV.COM 13177 6475 deflated
AS0.DOC 8770 3859 deflated
AS0.EXE 18449 10751 deflated
MAIN.DOC 3098 1356 deflated
MAIN.S19 18284 6315 deflated
SPEED.O68 758 303 deflated
TASM68.TAB 9137 2095 deflated
TPCREAD.ME 199 165 deflated

Download File 68EM.ZIP Here

Contents of the 68EM.TXT file


Version 1.0

1 - May - 1991

Kevin Bertram


This implementation of the M6800 Emulator is version
1.0. If you find any errors with the Emulator or debugger or
maybe there are a few suggestions as to what you might
like to see in the program to enhance its usefulness then
please let me know. My address is further down in this

Also this program and manual can be copied as many
times as you want and given to friends if you please. There
is no hassle with this. But do not sell it! The program is
public domain and not for profit making.

The purpose of this Emulator is to replicate the
instruction set execution of a CPU not present within the
hardware design of the IBM-pc-xt/at or a clone there-of. Or
for that matter any host computer that is capable of
executing programs. The instruction set of the emulated CPU
must be adhered to exactly otherwise programs written for
the emulated CPU will not perform correctly in the target
system. This program in particular has been adapted to suit
the Motorola M6800 8 bit CPU.

An emulator can be a useful program. Especially if you
are into constructing and programming your own micro-
controllers. They provide for a safe environment at which
new code can be tested under reasonably tight control before
being downloaded to the target machine and let loose. Also
the emulator allows for a foreign CPU's machine code to
execute under a host CPU. Which is most likely where the
cross-assembler will reside too. All this adds to faster
implementation of your program and gets you to using your
hardware sooner.

I will not enter into the reasons as to why a designer
might use 8 bit CPU's as opposed to 16 of 32 bit CPU's but
rather that what ever his or her choice is they might find a
need to check out the integrity of the program code before
'burning it in'. It could be that the program will have to
be executed step by step to find an illusive fault. And in
this case an emulator could prove useful. If the target
machine already has a debugger built in then there might be
no need for an emulator but if there is not then an emulator
will be needed.

My reason for producing an Emulator for the M6800 is
mainly because it was the first CPU I had encountered and so
I am biased towards it. Another is that, as far I am aware,
there are no other programs that will emulate a M6800 CPU
running under an Intel CPU and as I have a need for one
right now I wrote this program as a response. So here it is.
It was a joy to work on and I hope you find it useful.

Kevin Bertram

Electronic mail

ACSNET - [email protected]

Surface mail:

Department of Computer Science
La-trobe University
Plenty road
Bundoora, 3083
Melbourne, Victoria


I would like to thank Ira Baxter for his excellent
suggestions in speeding up the Emulator to the effect of ten
times as compared to its intial implementation.

I would like to thank Mark Seiffert also who, along
with Ira, sourced me with M6800 code to run through the
Emulator to test its validity. [I find it is much better to
have someone else test my software because they will not
step around the precarious parts of the program.]


There should be the following files contained within
the archive file.

68EM.COM M6800 Emulator configured for a
standard IBM-pc-xt/at

68EMV.COM M6800 Emulator configured for an
IBM-pc with a VT-100 terminal as
its console.

68EM.TXT This file - it describes the usage
and other things present within
this version of the M6800 emulator.

68EM.PIF Windows information file to get
this emulator to run in a window.

68EM.ICO Icon for emulator to suit Microsoft
Windows V3.0.

MIPS.o68 Runs through a general selection of
M6800 instruction 65535 times. By
timing this an indication of the
instruction through-put can be
calculated. See Appendix D

TASM68.TAB M6800 opcode table suited to SPEECH
table driven cross-assembler
version 2.2

AS0.EXE M6800 assembler from Motorola as
freeware software.

AS0.DOC Document for the Motorola

MAIN.S19 Sample multitasking operating
system that will run under the
control of the this CPU emulator.

MAIN.DOC A brief description of the sample
operating system (MAIN.S19) and how
to use it.

Note that the cross-assembler by SPEECH TECHNOLOGY
INCORPORATED has not been included. Their program can be
acquired from any BBS that has it and will most likely be
named as TASM22.ARC

Notes on how to use TASM will come with the archive
file. Also see the section in this document on "Extra
instructions" for extra details concerning the cross-
assembler in relation to this program.


There is nothing very special about the way in which
the debugger or Emulator will display its data to the
console. That is there are no fancy windows or graphics
included to improve the overall look of things. But rather
the output is simple.

There is, however, a need to setting certain things
such as high brightness characters, a limied number of
cursor addressing movements and clearing the whole screen.
For these I have catered for two environments on which this
program could run. The first is the standard "run of the
mill" IBM-PC-xt/at with what ever graphics card being used.

The second is for a IBM-PC type computer that runs the
same programs but uses a VT-100 character terminal as its
console. These do exist (I've got one!) and therefore I have
adapted the program to suit them too. In fact if the
standard XT/AT were to have the device driver ANSI.SYS
installed then there would be no problems in running the
later program on either machine.

I have thought about using a soft switch within the
command line when the program is invoked to indicate which
console type is being used but decided against that, at
least for the moment, to opt for two programs. One setup for
a standard console using graphics cards and the other being
setup up for VT-100 consoles. It is no big deal to do this
as all it requires is one variable to be changed within the
source at assembly time.

The main reason for this approach is to take into
account those times when a programmer is fanatically working
at great pace and would much rather type a simple name to
start the program instead of the name and a string of
softswitches. It can be discouraging to start the program in
the wrong mode and wonder why all these strange characters
are appearing on the screen.

Anyway it remains to be seen as to whether softswitches
are included or not later. But at this moment they are not.


To start the program it is a simple matter of typing
its name then pressing return. The program will load and run
and the command line prompt '-' will appear.

If there is a data file to loaded as well then this can
be done by including the data file's name after the
emulators invocation name.

For example C:> 68em example.o68

Will load example.o68 into the Emulators memory
after it itself has been loaded and run. All of the
error checking steps that are done by the 'L' command
apply. If there is an error loading the file then an
error message describing the problem will be printed
and the loading terminated. The Emulator will return
with its prompt waiting for a command but with no data
in memory. If the file loaded correctly then the byte
count will be displayed followed a report on the
highest and lowest address data was stored at, the
Emulator's signon message and then the prompt '-' on
the last line. The debugger and emulator will now be
ready to use.

Note that the hello message after starting will contain the
current version number, the initial release date and its
version number and finally the current version of the
program along with its release date. This should give the
user an indication of what version of the program they have
and whether it is as recent as it should be.

After a succesful load of a data file on starting the
Emulator the Program Counter (PC) and all of the default
addresses used within the debuggers commands will be set to
the same value as the lowest address data was stored at.
This makes for a quick and easy startup of a 6800 program
that will require the user to merly enter a 'G' command to
start the application.


In order to make the Emulator useful then there must be
some way of reading and writing to the Emulators memory,
tracing execution of test programs, examining or changing,
registers and loading data from files which will be more
than likely be output from cross-assemblers. The M6800
Emulator has these functions and they will be described

The usual format will be:


If an 8 bit constant is required in any of the commands and
a 16 bit constant was entered then only the last 8 bits
will be retained.



* S

Toggles the mode in which the emulated code will run
in. Initially, after begining the emulator, the program will
be executed in the 'Supervised' mode in which program
execution can be stopped at any time by entering a ^C. A 'G'
command will return the program back to its previous
position unchanged before the interupt was encounted.

By issuing the 'S' command and toggling to 'Non
supervised' mode programs will run until a breakpoint or an
illegal opcode is found. There is no other way to exit. Mind
you though that the later mode performs 3 times better than
the 'Supervised' mode. The use of either mode will be
determined by whether you trust the code or not.

If a program is running in unsupervised mode and a
control-c was entered at the keyboard then this character
will be passed onto the internal keyboard buffer ready to be
read by the 6800 program through the CHINT A instruction.
This will allow for a reasonable emulated environment for
the 6800 program to work in. That is: a control-c will be
allowed to be processed by the program as if it was on its
target machine.

* Q

Quit from the Emulators debugger and return to DOS. The
return code given to DOS will be $00.

* ?

Prints the quick help menu to the console.



R A < 8 bit constant>
R B < 8 bit constant>
R X <16 bit constant>
R S <16 bit constant>
R P <16 bit constant>
R F < 8 bit constant>

* A, B, X, S, P, and F

As with any M6800 CPU chip there are five user
registers which can be changed under program control and as
such they can be modified at anytime through the use of the
above commands. The Flag register, although not ideal for
storing data in, can have it's contents changed too. This
would most likely be used to set up key situations which
would test program integrity at a point without the need to
execute code before it.

'A' - sets the A accumulator
'B' - sets the B accumulator
'F' - sets the status flags
'X' - sets the index register
'S' - sets the stack pointer
'P' - sets the program counter

* R

Without a register name will print the entire register
list along with the disassembly of the next instruction.
Note that if a register name is given of which the program
does not understand then the register list will be printed
instead of an error message. A print of the register list
will have the flags printed as a hex number and a single
letter description of each flag bit, the contents of the
five other CPU registers that are relavent to the M6800 CPU,
and a disassembly of the next instruction to be executed.

A typical register list would look like this:

F - FF - - H I N Z Ov C
A = 12 B = F7 X = 0147 S = FFF8 PC = 0100

0100 86 45 LDA A,#$45


The Flags list mean:

H - Half carry flag
I - Interupt enable flag
N - Sign bit flag
Z - Zero flag
Ov - Overflow flag
C - Carry flag



* C

The 'C' or 'fill memory with Constant' command will, by
default, fill all of the Emulators 64K memory space with
$00. Thus the work space can begin from a clean slate. If a
start address is given, as the only parameter, then it and
the following 256 bytes of memory will be set to null, $00.
If a start address is given with an end address but with no
constant then that area of memory within the start-end
address will be filled with nulls, $00. But if a constant is
supplied that range of memory will be filled with that

For example : C 100 200 01 will fill the address range
from $100 to $200 with $01
which are "nop's".

* E

'E' or 'memory Examine' and change will allow single
steps through the Emulators memory space. At a point where a
byte is to be changed then a new value can be entered, or a
string of new data can be entered each seperated by a space
character. When the [return] is entered then that data is
stored to memory and the next unused address is displayed
ready for new data. To exit this mode a '.' with no other
data on the line should be entered followed by a [return].

Example: -E 100

0100 00 > _ will be the response.
Entering data will be
like this:

0100 00 > 01 02 03 04 [return]
0104 34 > _

with only a [return] on
the input line then the
address being looked at
will increment by one.

0104 34 > [return]
0105 31 > _

To exit now just enter
'.' [return]

0105 31 > . [return]



* D
* H

Dump or Hex dump will both do the same thing; print a
block of data using byte size data along with it being
printed as an ASCII character as it would appear on the
screen. After using many different types of debuggers some
use 'D' for this function and others 'H'. When changing from
one to the other more than likely 'D' will be entered
instead of 'H' and visa-vers. So I've included these two to
do the same thing to accommodate for my limitation at least.

The default block dump size is 256 bytes but if an end
address is given then the hex dump will end at the end
address. Note that both the start and end address will be
rounded off to the lowest 16 byte field. That is $102 will
be taken as $100, $159 will be taken as $150 etc.

The output will be:
address, 16 bytes of data, ASCII field

As an example:
-D 100 110

0100 - 01 02 03 04 34 31 0 45 20 10 11 13 45 48 2a 20
.41.E ...EH*


will result. Note that all unprintable characters will
appear as a single '.' in the ASCII field.

* U

Uncompile will disassemble a section of code from the
M6800's memory. The default listing length will be 16 lines
of disassembly but given a start and end address then the
disassembly will continue until the end address has been
reached. If only a start address was supplied then the
disassembly will print 16 lines of disassembly from that

If an address of an instruction appears in the
breakpoint list then that line of disassembly will be
highlighted to make easier viewing of the code and the
breakpoints position within it.

The disassembler follows the usual rules concerning the
M6800 instruction set as it appeared on the day. But there
is one exception to the rule. When printing an instruction
that uses INDIRECT addressing mode then the disassembly will
have 3 parts to its opcode field.

For example: LDA A 2,X will appear as LDA A,2,X

Most assemblers will not accept this kind of notation
but in preference for neatness I have opted for this instead
of the alternatives. Motorola had changed the Mnemonics
somewhat to accommodate for this problem it seems by using
LDA or LDB in the 6809 series rather than LDA A or LDA B.

* Z

This command will print the last twenty executed
instructions that the emulator has just worked on before
exiting the 6800 program. The very last instruction printed,
which is more than likely to be the cause of the exit, was
the last instruction processed.

The purpose of the command and instruction tracing will
be seen when you are trying to find a reason to why a
program has become a "run-away". Or why a program sourced by
someone else always exits without performing anything

It should be pointed out that no instruction tracing
will be performed when the emulator is running in
unsupervised mode. In fact not much is done eccept 6800
instruction execution in this mode. All of the goodies are
done in the supervised mode. Also when a program is run in
unsupervised mode the instruction trace buffer is cleared
thus to issue a "Z" command after a program has been
executed the buffer will be reported as empty. This happens
even if it was full before execution in unsupervised mode.


B <#>


Executing any M6800 program is simply a matter of
loading the opcodes and data into the Emulators memory then
instructing the emulator to take control. Three instructions
are provided to help do this. Their usage desription

* G

Goto will cause the execution of M6800 instructions
from the address '' if given or from the
current value contained within the M6800's Program Counter
(PC). The command line address will always override the PC's
current state.

If at anytime the Emulator tries to execute illegal
instructions then the CPU's current state will be saved and
program execution ceased. A message will then be printed and
the program returned back to the command line entry level.
To gain an understanding of what the CPU's current state was
use the Register command. See the 'R' command for usage

* T

Causes the Emulator to trace 'n' instructions at a time
then return back to the command level. The default value for
'n' is one (1) but can contain values upto 255. This will
make it easy to get passed those loops that might be
contained within the program under test.

The actual execution address is read from the CPU's
Program Counter (PC) and instructions taken from there.
There is no provision for overriding the Program Counter
within this command.

The current state of CPU is saved away for viewing
later and control returned to the command level. If illegal
instructions are encountered then the Emulator performs the
same abort sequence as described in the 'G' command.

* B

Breakpoints set or cleared within the M6800 program.
Upto eight breakpoints can be set at any one time and the
list will be shown when the 'B' command, alone, is entered.
If a breakpoint number is given but no address stated then
that breakpoint will be cleared from the list and finally if
an address is given with a breakpoint number then it will be
set; or changed if that breakpoint number already exists.

Note that a breakpoint address of the value of $FFF8
will clear the breakpoint from the list. I have used this
value instead of the usual $0000 to indicate cleared
breakpoint. Why? Because those values contained at the
address $FFF8 - $FFFF are autovectors for interupt control.
They are never instructions, or if they are then the
function of the M6800 could be eratic at times. As there are
no interupt functions other than a software interupt, built
into the Emulator then it would be reasonable to use this as
a sort of null value or useless address and in this case 'no

* P

Will cause execution of the next instruction to
completion. If it happens that the next instruction is a
subroutine call then the subroutine will be executed and
allowed to complete and return to its caller. At this point
the program execution will stop and the register list will
be printed as would any trace command do.

This command is extremely useful in step over those
subroutines that have been tested and proved working. Thus
preventing worthless tracing of code that has been verified.



* I

The M6800 emulator version 0.3 and up all support
interupt handling for all of the interupt types supported
within the M6800 CPU. Versions before 0.3 only catered for
the Software interupt. In order to implement the other two
interupts other than reset this command exists. Note that
when an interupt is to occur the service routine address is
read from the NMI and IRQ vectors at $FFFC and $FFF8

Entering "I" with no parameters will print the status
of the registers that will keep track of when Non Maskable
and Maskable interupts should occur. The mechanism for
determining when either of the interupts should be invoked
is by instruction count rather than an external signal of
some type. Therefor you will have to work out how many
instructions the target CPU will execute before the next
interupt will occur. This is by no means the best answer to
interupt servicing for all target environments but at least
it does give you the user a way to test if an interupt
service routine will work with the reset of the program.

For those instances that required regular interupt
signals such as 20 millisecond clocks in real time can be
tested using the interupts within this emulator. As the
speed of the system that this Emulator will be run on varies
from system to system calculation of the instruction count
per 20 milliseconds will differ and assuming you want the
program under development to appear as real as posible in
real time then the Emulator speed has to be worked out. (See
Appendix D for more information on this)

The interupt priorities appear as they would in the
real thing. That is NMI has the most priority, then the IRQ
interupt that will occur only if the interupt mask in the
status flag is clear. An IRQ interupt can not interupt an
interupt service routine already in process, whether it be a
NMI or IRQ service routine running. But a NMI can interupt a
IRQ or NMI service routine in process. Here lies a danger
that is not protected against. If the NMI instruction count
is set to a value lower than will allow a NMI service
routine to finish to completion and return on the first
interupt then nested interupt servicing will occur and
before long the whole memory space will be overwritten by
the stack thus destroying the users program.

* I N

Loads the Non Maskable Interupt instruction count
register with a constant. If the constant was equal to $1000
then the program will be interupted by a NMI every 4096
instructions executed.

* I I

Loads the maskable interupt request register (IRQ) with
the value constant. If the constant was $200 then the IRQ
interupt will occur every 512 instructions but only if the
interupt mask is clear.



* L

Load file from disk of the filename will
cause the debugger to attempt to load data from a mass
storage device. But before this can occur four checks will
be done.

(1) The filename's extension string will be checked for one
of eight types. They are: .S1 .S2 .S3 .O80 .O68 .HEX
.COM .EXE If the extension string does not match
with any of these then an error message is printed and
the function terminated.

(2) An attempt to open the file proceeds. If this cannot be
done for some reason then the reason is displayed and
the function terminated.

(3) If the file is of type .COM or .EXE then a straight
binary load is performed and load exits. But if it is
anyone of the other type of files then the debugger
will interpret what type of format the data is stored
as then decode and store it into the Emulators memory.
The format is determined by the data contained in the
file. Any one of the Motorola formats or Intel hex
format can be read. As these follow strict layouts then
the type can be determined and the data checked against
checksum values. After the end-of-file signature has
been found the debugger exits from loading the data.

(4) If this is a load on entry to the emulator. That is a
filename was stated in the command line at startup.
Then the program counter (PC) will be set to the lowest
address data was stored at. All default values within
the debuggers commands will also be set to reflect the
contents of the PC.

If no filename is given then the last used filename will be
used. That is assuming a file has been loaded within the
same session.

After a succesful load has been completed the lowest and
highest address that had data stored to it from the source
file will be displayed. This will help in determining where
that run-away data went.

More detailed information on the format of any of the
Hex formats can be found in APPENDIX B and APPENDIX C. These
should describe it sufficiently enough.


One of the great advantages that came with writing this
emulator is that of creating my own instructions. Athough
the instructions that have been added to the MM6800-
Emulators repertoire are simple ones it is not unreasonable
to include instructions that are very complex in there
nature. That would mean that a Float Point Unit could be
emulated along side the M6800 CPU with the intention that
this FPU chip will be included into the final system. All
aspects of the two chips could be tested. Albeit at the
software level only.

FPU functions have not been implemented in the MM6800-
Emulator but instructions a little more basic have. These
are supplied as an interface to the IBM-pc's hardware and
console. Their purpose is to allow information to be
displayed by the M6800 code to the user under its own
control rather than the interuption of processing by the

Four other instructions for reading and writting to the
IBM-pc's input/output ports are supplied also to allow I/O
chips to be used and controlled under the M6800 program. If
ever you have had to develop programs for micro-controllers
that look after the up-keep of peripherals, and there is no
way of doing this in the development system, it can be
frustrating. Its never quite known for sure whether the
perihperals' registers have been set right. Even a bit of
real time, real world, implementation could be undertaken
using the IBM-pc's I/O ports.

In the end it's all up to the developer as to how
testing is implemented. And if you wish to use these extra
instructions then by all means do so that's what they are
there for. There are however two protection mechanisms
included to prevent these opcodes from being included into
the target systems environment and these appear in the
debugger's Uncompile command and at the Cross-assembler's

The Uncompiler will show the extra instruction by
displaying them in brackets like this

0100 41 (CHOUT A)

And the assembler will have to have a mask value set within
the invocation command line to cause the instructions to be
assembled correctly. Normally the mask will default to a
value that will not allow these instructions to be assembled
and an error message displayed.

The command "tasm -68 test.asm" will not
assemble the new instructions into the final program and if
they are present will cause error messages to be printed.

The command "tasm -68 -x1 test.asm" will assemble the
new instructions successfully into the output.

With all this said it only remains that the
instructions be listed. But be aware that none of them
affect the status flags of the CPU. Unlike most register
modifing instructions within the M6800 standard instruction

Character output to console CHOUT

Operation: ACCX -> IBM-pc-xt/at standard output

Description: The 8 bit value taken from the A or B
accumulator will be sent to the standard
output device of the host computer.

Condition Codes: None

Addressing format:

Addressing | Execution | Number of | Opcode description
Modes | time | bytes | HEX
A IMM | Undefined | 1 | 41


LDA A,#'e'

Character input from console CHINT

Operation: ACCX <- IBM-pc-xt/at standard input

Description: An 8 bit value is read from the standard
input of the IBM-pc-xt/at and stored
into the accumulator defined within the

Condition Codes: None

Addressing format:

Addressing | Execution | Number of | Opcode description
Modes | time | bytes | HEX
A IMM | Undefined | 1 | 51


BNE Example

Read a byte from the 80x86 I/O bus IN

Operation: ACCX <- (XREG)

Description: The X register is placed onto the 80x86
input/output bus and an 8 bit value is
read from it storing it to the
Accumulator defined.

Condition Codes: None

Addressing format:

Addressing | Execution | Number of | Opcode description
Modes | time | bytes | HEX
A IMM | Undefined | 1 | 61
B IMM | Undefined | 1 | 62


LDX #$1000

Write the Accumulator to the I/O bus OUT

Operation: ACCX -> (XREG)

Description: The X register is placed onto the 80x86
input/output bus and an 8 bit value is
written to it from the Accumulator

Condition Codes: None

Addressing format:

Addressing | Execution | Number of | Opcode description
Modes | time | bytes | HEX
A IMM | Undefined | 1 | 71
B IMM | Undefined | 1 | 72


LDX #$102



Opcode b7 b6 b5 b4 b3 b2 b1 b0
| | | | | | | |
| | | | | | | |
| | | | -------------- Function
| | | |
| | ---------------------- Addressing Mode
| |
| |
| |
------------------------------ Set selection

Opcodes from $00 - $3F seem to be of no set pattern but
rather allocated a random place. The other three sets of
instruction, however, do follow an easy pattern. It can be
considered that bit-6 determines which register will be used
as follows.

b6 Register selected
0 A register Index register
1 B register Stack pointer

The Operation that is to be perform on the SETS is
contains within b0 - b3. The function is described in the
SETS tables below. Each SET for each group of instructions.
The instruction SETS follow:

0 - NEGate 8 - Arithmetic Shift Left
1 - illegal opcode 9 - ROtate Left
2 - illegal opcode A - DECrement
3 - COMpliment reg B - illegal opcode
4 - Logical Shift Left C - INCrement
5 - illegal opcode D - TeST
6 - ROtate Right E - JuMP
7 - Arithmetic Shift right F - CLeaR

b5 b4 Addressing Mode
0 0 A
0 1 B
1 0 Indirect
1 1 Extended

SET 2 ($40 - $7F)

0 - SUBtract Areg 8 - Exclusive OR Areg
1 - CoMPare Areg 9 - ADd with Carry Areg
2 - SuBtract with Carry Areg A - OR Accumulator Areg
3 - illegal opcode Areg B - ADD Areg
4 - AND Areg C - ComPare reg (16 bit) Xreg
5 - BIT test Areg D - Subroutine call
6 - LoaD Accumulator Areg E - LoaD reg (16 bit) Xreg
7 - STore Accumulator Areg F - STore reg (16 bit) Xreg

b5 b4 Addressing Mode
0 0 Immediate
0 1 Direct
1 0 Indirect
1 1 Extended

SET 3 ($80 - $BF)

0 - SUBtract Breg 8 - Exclusive OR Breg
1 - CoMPare Breg 9 - ADd with Carry Breg
2 - SuBtract with Carry Breg A - OR Accumulator Breg
3 - illegal opcode Breg B - ADD Breg
4 - AND Breg C - ComPare reg (16 bit) Xreg
5 - BIT test Breg D - Subroutine call
6 - LoaD Accumulator Breg E - LoaD reg (16 bit) Xreg
7 - STore Accumulator Breg F - STore reg (16 bit) Xreg

b5 b4 Addressing Mode
0 0 Immediate
0 1 Direct
1 0 Indirect
1 1 Extended

SET 4 ($C0 - $FF)



The Intel Hex format data records are pretty straight
forward. They are constructed with a character to indicate
the record is starting ':', an address field of 16 bits, a
record type field, a data field and the checksum. All of the
values printed are first converted to an ASCII equivalent
then sent. So to send, in the address field, a value of
$4090 as a string would be '4090' but to view that number as
byte values will be $34 $30 $39 $30. Each four bits have
been converted to an ASCII equivalent. This applies to all
values that appear within the record bounderies. Moreover
the whole record is printable and any system dealing with
these records will not hangup or perform strange things
while trying to dump it to the serial port.

| : | CC | AAAA | TT | DD .. DDn | XX |

':' Start of record character char
'CC' Byte count. Size in bytes of Data field. 8 bits
'AAAA' Address field. 16 bits
'TT' Record type.
00 = normal data, 01 = last record. 8 bits
'DD' Data in bytes, no spaces between any values.
The data field can be of 1 to 255 bytes long.
8 bits
'XX' Checksum. 8 bits

The checksum is calculated like this:

Temp = CC + AA(high) + AA(low) + TT + (DD .. DDn)

XX = 0 - Temp

Therefore to verify a record against its checksum simply add
all of the fields together and the answer should be $00

00 = CC + AA(high) + AA(low) + TT + (DD .. DDn) + XX

To determine the end of the total file two methods can be
used. One is to check the 'TT' field for a value of $01. But
this can be a bit dubious as some programs that generate
Intel hex format records don't worry about this field and
leave it with a value of null, $00. The second method is to
check if the 'CC' field has a null value in it. When it has
then it can be assumed that no more data will follow. This
seems to be the accepted way of terminating an Intel hex


This Example has data in it that came from
addresses $100 - $104. That data is $01, $02,
$03, and $04. The Data field byte count,
'CC', is $04 and the record type is $00; a
normal data record. The checksum is $F1.



There are three types of 'S' format records that can be
generated by a cross-assembler. Although you can be assured
that the 'S1' format records will be generated by M6800
assemblers I will include the other two for completeness.
These are 'S1', 'S2', and 'S3' formats. See the table below
for a full layout of them but mainly the value 1, 2 or 3
indicates what size the address is in the Address field. The
end of file 'S' values indicate that this will be the very
last record within that file. Nine times out of ten 'S9'
will be used in all cases but it is a good idea to test for
all three anyway. That is assuming your loader is programmed
to decode all three.

The construction of the record is the starting
character 'S', record type, byte count, address, data field
and finally the checksum. It must be pointed out that the
calculation of the checksum is slightly different to that of
the Intel hex format. Instead of a value of $00 when all
fields have been added together $FF is the result. But this
will be described in detail later.

As with Intel hex records all byte quanties are of
printable form so every four bits are converted to an ASCII

S0 - Data field contains name of the source file.
The address field will usually be a 16 bit null, $0000.

S1 - 16 Bit address field End of file -> S9

S2 - 24 Bit address field End of file -> S8

S3 - 32 Bit address field End of file -> S7

Table 1

S-format layout

| S | T | CC | AAAA | DD .. DDn | XX |

S - Starting character for the record Char
T - Record type. 4 bits
CC - Byte count. Includes address field, data field and
checksum field in the count.
8 bits
AAAA - Address field. For 'S1' type. 16 bits
DD - Data field. No spaces between the bytes 8 bits
XX - Checksum 8 bits

Calculating the checksum is as follows:

Temp = CC + AA(high) + AA(low) + (DD .. DDn)

XX = $FF - Temp

Verifing the Integrity of a record with the checksum the
following should be done.

$FF = CC + AA(high) + AA(low) + (DD .. DDn) + XX

But for even easier checking of the record against a
checksum instead of clearing the accumulator that will keep
a tally of the checksum calculations start it with $01. Then
when the final value, the 'XX' field, is added to the
accumulator the result will be zero. Z flag gets set, no
need to compare it against $FF.

To further describe the 'S0' record which contains the
source files name or anything else look at the example
below. The source file's name is contained within the data
field but each byte that makes up each letter in the source
file's name 'test.asm' is taken as a byte literal and
converted to printable form like any other byte to be
inserted into the record. Other than that the record follows
the same rules as would any other record type within the

S0110000746573742E61736DBF <- "BF" = Checksum
^------------ Source filename


This 'S1' record has in it data from addresses
$0100-$0104 of the value $01, $02, $03, and $04
the data field is 'CC' - 3 (ie: $07 - $03) = $04
and the checksum is $ED
The next line has on it an S9 which indicates the
end of file.



To calculate the speed at which the Emulator is
processing M6800 instructions run the program MIPS.o68 with
supervisor mode turned off (use 'S' command) and begin
execution with 'G 100 [return]'. At the same time start
timing with your trusty time-piece until an illegal
instruction exception is reported. Stop timing. This value
is now time.

Now put the value time through the following formulae
to get instruction through-put (IPS) and equivalent clock
speed (clk) that a real M6800 cpu would have to be running
at to equal the performance of the Emulator.

IPS = (3 + (46 * 65535))/time (seconds)
clk = (9 + (152 * 65535))/time (seconds)

Here are some figures that I have gained from various test
machines. All IBM-pc compatable.

80386 @ 20MHz. Time = 25.3 seconds
Calculated: IPS = 119,154 Instructions per second.
Calculated: clk = 393,728 Hz M6800 cpu.

80286 @ 12 Mhz. Time = 37.8 seconds
Calculated: IPS = 79,751 Instructions per second.
Calculated: clk = 263,527 Hz M6800 cpu.

80286 @ 8MHz. Time = 64.7 seconds
Calculated: IPS = 46,593 Instructions per second.
Calculated: clk = 153,962 Hz M6800 cpu.

80186 @ 10Mhz. Time = 65.1 seconds
Calculated: IPS = 46,307 Instructions per second.
Calculated: clk = 153,106 Hz M6800 cpu.

80c86 @ 9.5 Mhz. Time = 81.3 seconds
Calculated: IPS = 37,080 Instructions per second.
Calculated: clk = 122,525 Hz M6800 cpu.

80c86 @ 4.77Mhz. Time = 163.3 seconds
Calculated: IPS = 16,855 Instructions per second.
Calculated: clk = 61,000 Hz M6800 cpu.

 December 5, 2017  Add comments

 Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>