Q. Are all offsets
in this addressing mode from the program counter?
A None of the indexed addressing
mode variations use an offset from the program counter, with one exception
- the format INST n,PCR. All offsets apply to the specified register Eg
X for INST n,X and Y for INST ,Y.
Q. In example
3.1, to manually store values in mem1, and mem2, would you include lines
in your program: lda #$XX sta mem1...
A. You could add these lines to your progam if you wish,
but I meant to use the Memory command in the simulator to change the contents
prior to running your program.
Q. In example 3.1, should the program
be addressing $0000, as wouldn't this be I/O?
A. The I/O area is located in different places for different
micro-computers and different families of micros. To determine where the
I/O is you should consult the memory map for the micro-computer you are
working on. In the 6809 simulator you can use memory at any address except
$D000 and $D001 where the ACIA is positioned.
Q. org $8000 is chosen, is this
because RAM begins at that address? How do you know where RAM begins and
ends on the 6809 to avoid using the address for ROM or I/O?
A. I have set the $8000 address in the examples to make
them compatable with the micro-computer hardware in our labs here at USQ.
Here in the lab the RAM starts at $8000. To determine where the RAM is
you should consult the memory map for the micro-computer you are working
on. In the 6809 simulator you can use memory at any address except $D000
and $D001 where the ACIA is positioned.
Q. In example 3.2. Does each memory
location refer to a word which in the 6809 is a byte, so as D is a 16 bit
accumulator, when you load D with mem1hh, it loads in mem1hh mem1hl?
A. Each memory location in the 6809's memory is a byte.
When you load D (or X, Y too) you load two consecutive bytes as in LDD
mem1hh, loads both mem1hh mem1hl
Q. In example 3.2. Does the line
"bcc over" branch to subroutine "over" if there is a carry (or if the carry
flag is set to zero), then, on a branch, when the subroutine is completed,
it returns to add 1 to D, and then does it do the subroutine again? - if
so, what does it do when it reaches rts the second time?
A. Only instructions JSR, BSR and LBSR call subroutines.
All other branch instructions 'Bxx' simply decide whether to branch or
not according to condition 'xx'. If no branch is required the instruction
after the Bxx is executed. If the the condition is true then the PC is
changed to cause the change in the program flow. This is achieved by adding
the offset part of the instruction to the PC.
Q. In example 3.3, what happens
at the line "ldx #table", where table is 32 bits and the X register is
16 - does it only load in the first 16 bits?
A. table is a label, which is used by the assembler to
mark a position ie an address. The contents of the memory at the address
table may be anything. Labels are often used to mark the start of - an
area of memory, or a string of characters or numbers. By using ldx #table
the X register is loaded with the address of table.
Q. In example 3.3, rts is used but
there is no call, is this program only a function of a larger program?
A. Yes, the way I have written these examples is as a
set of subroutines, to encourage you to think of structuring your code
in modules. See the note at the bottom of Example 3.1.
Q. In example 3.4, does cmpa 0,x,
mean subtract the value at the address 0 offset + contents of X from the
program counter, from accumulator A, and fill in the condition code register,
so it can be tested for zero or negative?
A. The cmpa 0,x subtracts the value at address {0 (offset)
+ contents of X (an address)} - from accumulator A. There is no reference
to or use of the PC. Almost all instructions update the CCR.
Q. In example 3.4, does leax 1,x,
mean calculate the Effective Address offset 1 from the program counter
+ contents of X, and place this value in X?
A. leax 1,x loads the effective address (the calculated
address of 1 (offset) + contents of X) into X. Equivalent to INX in 6802
but the offset can be any value. There is no reference to or use of the
PC.
Q. In example 3.6, what does decimal
adjust A do in line 11?
A. DAA is used after an ADDA when doing BCD arithmetic.
consider BCD 58 + 45. The BCD values are stored in the memory as $58 and
$45. When ADDed the result in hex is $9D. Following the ADDA the DAA makes
the CPU check the result for values > 9. Here a DAA would cause the D in
the units column to change to a 3 and cause a half carry (H in CCR) - equivalent
to 13. The half carry plus the 9 in the tens column would give A, the DAA
would change this to a 0 and a carry - equivalent to 10. Tthe result would
be C=1 (hundred) A = 03 ie 103.
Q. In example 3.7, what is the difference
between extended indirect addressing in line 13, and ldd a,x?
A. This example is meant to illustrate the difference
between INST n,X and INST [n,X] as follows
- INST n,X loads the specified register with the contents of address {n + contents of X)
- INST [n,X] loads the specified register with the contents of address at the address {n + contents of X).
Eg if X = $0000 and a = 2 then ldy a,x loads the contents of address 0002
if X = $0000 a = 2 then ldd [a,x] loads the contents of the address 3000, found in address 0002.
Q. In example 3.8, what is bita
in line 7, does it read in the value at $0001 and test it against the condition
code register?
A. BITA is like an ANDA except the resulting value is
not put back into A, just the CCR is updated. in the example the value
in A %00010000 is anded with the randno variable in memory to check if
bit 4 (5th from right) is a ON or not. If bit 4 = 0 the branch equal test
is true.
Q. In example 3.8, In line 9, is
comb the two's complement or one's complement?
A. COMB is a 1's complement instruction. NEGB would be
a 2's complement.
Q. In example 3.8, In line 17, does
the least significant bit become the carry and the most significant bit,
and is there a logical shift right?
A. The ASRB instruction shifts right B one bit dropping
the LSB into the carry. The ROR randno instruction loads the byte in randno
into the ALU and shifts it right one bit. The LSB from B in the carry is
shifted into the MSB of randno and randno is placed back into memory. The
LSB falls into the carry but is not used here.
Q. I do not understand what has
been said on the four types of addressing
mode:- Absolute, Indexed non-indirect,
Indexed indirect and Relative.
A.Absolute includes several
sub groups, but basically -
Absolute addressing is used in instructions where the
data is located at a known address. Eg
LDA $1000
loads data into A from the address $1000
this is an extended address because it uses a full 16
bits to identify the address. The address is fully known at the time the
program is written.
another form of this absolute addressing is direct addressing
which determines it's address with the aid of the DP register. Eg assuming
DP = $21
LDA $50
loads data into A from address $2150
The address is also known at the time the program is
written.
immediate addressing falls into this category as well.
In immediate the data becomes part of the instruction. Eg
LDA #$8F
loads the value $8F into A
The address for the data is actually part of the program
and thus is known at the time the program is written.
Indexed Non-Indirect is the simplest form of indexed addressing -
This addressing mode is used when the address required
to fetch data is unknown or changes during the program running. Eg
LDX #$2000
loads the X index register with the address $2000
LDA 0,X
loads the data into A from the address X holds ($2000)
that is - the contents of X point to the data. The 0
is an offset that can be
applied to access data near to that address. Eg
LDA 7,X
loads the data into A from the address X holds+7 ($2007)
There are other variations on the offset including using
the A, B or D accumulators to provide the offset. One of the main uses
of indexed addressing is to move through a table of values by changing
the index register value. Eg
LDX #$2000
loads the X index register with the address $2000
CLRA
clear accumulator A (=$00)
LOOP ADDA 0,X Adds the data into A from the address
X holds
LEAX 1,X
increments X by 1, equivalent instruction to INX (6802)
CMPX #$2010
checks if X = $2010 yet
BNE LOOP
if not loops back to add next number
This program adds the contents of addresses $2000, $2001
... $200F together in A
by using indexed addressing to fetch each data value
to add to A and then increment X to point to the next location. The leax
1,x uses indexed addressing too, but the LEA instruction means "Load the
Effective Address" not load the data, that is - work out what the contents
of X + 1 is and load it into X.
Indexed Indirect addressing
is more involved and you aren't likely to need it during this course, but
is provides one more level of indirection to the indexing. The term indirection
refers to X pointing to the data. To add another level of indirection we
could say - X points to a location which contains the address which points
to the data. This is written using [] brackets. Eg
assume the contents of addresses are as follows -
$2000 $40
$2001 $00
$4000 $5A
LDX #$2000
loads the X index register with the address $2000
LDA [0,X]
loads the value $5A out of $4000 after obtaining the address of the data
from the locations $2000 and $2001. remember that it takes 2 bytes to hold
a 16 bit address. offsets and register offsets apply to this mode as well.
Relative addressing mode is mainly used by Branch instructions -
Branch instructions use it to determine where to branch to when the branch test it true. The term relative actually means relative to the program counter. The PC identifies the location of the next instruction to run. Lets say it points to the start of a branch instruction. The CPU fetches the opcode for the branch and then increments the PC to the next location. The next byte that is fetched is called the offset, it is kept in the CPU until required. Then the PC increments to the next location - which will be the start of the instruction under the branch.
The branch test is made and if the result is false the
PC is already pointing to the next instruction ready to go. If the test
is true then the offset value is added to the PC to effect the branch to
a new location. The branch is said to be relative to the program counter
as the change is PC value is equal to the offset. Eg
$0010 BNE SKIP
tests the previous instruction for NOT EQUAL to 0
$0012 LDA $1000
this instruction would execute if the test is false
$0015 SKIP ADDA #$05 this instruction would execute
if the test is true
The bytes that make up the branch would be $26 for the Op code and $03 for the offset, that is - relative to the PC (after the branch) we would have to 3 to the PC value of $0012 to get to $0015. to jump back in programs the offset is -ve.
Q. What are the PIA and ACIA programs
on the disk used for and do I use them in the assignment?
A. The PIA and ACIA software that comes on the unit disk
is separate from the Simulator. PIA and ACIA are there to help you understand
the operation of the each of those devices individually. (the devices are
described in the text and referenced in Module 4)
Q. How do I run the examples provided
on disk?
A. To complete the assignment and run the examples you
need to use the simulator software. Follow the instructions in the appendices
to run and load the MC6809 simulator table and load a program into the
simulator. Note that some of the early sample programs do not provide any
data for the example program to run. Use the Memory access to change the
contents of the memory locations used by the program before you run the
example. To make the data 'stick' into the locations press enter after
each one is changed.
Use Esc to get out of memory entry
To run the sample program, identify its starting location (like $8000) and use the Registers command in the simulator to access the register values at ehe lower part of the screen. Move the cursor (use arrow keys) onto the PC (Program Counter) type the start address of the program and press enter.
Use Esc to get out of register entry
To run the program use the Execute command then choose Step Program to run it one line at a time. You will see a window on the left showing the instruction just executed and the registers will display the new register values. I don't suggest you use the Run mode as it is too fast on newer PC's and does not allow the simulated ACIA to accept characters.
To use the ACIA as required in the assignment, use the
Acia command to open a small ACIA window (top right) switch On the ACIA
by pressing enter. Esc to exit.
The ACIA address is $D000 and $D001.
Now when you run any program a second window will appear under the program execution window, which operates as a simulated ACIA. Any alpha-numeric keys you type on the keyboard of the PC will enter the ACIA Receive register as if they we typed on a terminal connected to it. Characters stored to the ACIA Transmitter by your program will send characters onto this terminal window.
Use the Arrow keys to step the program.
A more detailed explanation follows.
The ORG directives in the programs tell the assembler where to place the following data or program. An ORG for Data area and one for Program area are typical but you can use more.
The examples in the book start data at $8000 and program at $9000. These are just different areas of memory. In some of the examples (3.1 and 3.2) some data values must be entered into memory before the program is run. In each example the program starts at $9000.
[Note: Check that the ORGs in the
file are the same as in the book.
They may be $0000 and $8000. Make
sure you change them to $8000 and $9000.]
So to run example 3.1, load the exampl31.asm file into the editor and click on the Assemble button, this produces the machine code file exampl31.s19 and a listing file exampl31.lst. Check the listing file for errors (click on LISTING).
Click on the SIMULATOR button. Follow
the instructions provided on disk about the simulator as follows -
Once the Banner/Splash screen is
closed type L for load, T for table then type MC6809 in the small window
and press enter. This defines the processor used.
Then type P for program and type
exampl31 in the small window and press enter. Note the .S19 is already
there.
Then press <ESC> twice to get
back to the menu. The program is loaded but has no data yet.
Type M for Memory and ENTER for
View, enter 8000 for the address and ENTER. You should see a screen of
bytes with addresses down the left and across the top. This is where the
data values go for the program to add. Type 12 ENTER to enter this data
into the first location. Move the cursor one place to the right with the
arrow keys. Type 34 ENTER. You now have 12 and 34 (hex) ready to ADD.
Press <ESC> twice to get back
to the menu.
Type R for registers, the cursor
will move into the Registers window onto the A accumulator. Type a down
arrow to move it down to the PC. Type 9000 ENTER to set it to the starting
address of the program. Now the CPU knows where your program is.
Press <ESC> to get out to the
menu.
Type E for execute - a small window
will appear on the right. Always use the step mode. Press ENTER to step
the first instruction in your program at 9000. A larger window will appear
on the left showing the instruction that has just run.
Note the registers in the register
window have changed. A is now 12 the first value to add. Press the down
arrow key to step the next instruction. Now a contains 46 which is the
addition of 12 and 34. Press down arrow again - the next instruction saves
it to the memory at the next memory location. A still contains 46.
Press <ESC> to get out of stepping
back to the menu.
Press M for memory and ENTER to
view, then type in 8000 and ENTER to show the same area as before. Now
you should see 12 34 46 in the first three locations. the third one is
the saved result from the program.
TIP: Always stop before you step
through the RTS instruction in these examples as there is not program to
return to in the examples.
I suggest you try the same thing
with the other examples.
Exampl32 also needs data entered
before it is run, like above.
Exampl33 needs a value in Accumulator
A before it is run -
in that case there is no
need to set the memory, when you set the PC in the register window set
A to the value 02, and see what happens.
Exampl34 also needs a value in
A, try the value $25 as in the study guide.
Exampl35 needs 2 address entered
into $8000 and $8002 and a byte count in $8002
I suggest entering the following
values starting at 8000: 90 00 70 00 20
when this move program runs
it will copy the program at 9000-901f to 7000.
Exampl36 is like example 3.1 or
3.2 it needs data put in 8000 to 8003 first
in this case it need BCD
data ie values 00 to 99 representing decimal 0 to 99
Exampl37 is a bit advanced just
forget it for now.
Exampl38 shows how to create a
string of ASCII characters and send them to an I/O device which uses a
ready and an outport location. This can be a useful example for the assignment
when you need to send "Error in Input". You need to substitute the I/O
instructions in this example with a call to TXDATA from the command.asm
Q Does the Acia
have to be configured with the control register ever time we want to write
to it. Is the address for setting the control register for ACIA for /16
8 data no parity 1stop bit? $D001 or $D000.
A NO you can set the ACIA once at the
top of the program. The CR/SR is at $D000, TX/RX is at $D001.
Q. The instructions
'fcc' and 'fcb' do not appear in the instruction set in the study guide,
or the text. Where can I find them? What do they do?
A. Fcc and Fcb are directives to the
assembler and not instructions for the CPU. You can find an outline of
them and usage in Module 3 page 3.22, and in the examples. They are designed
to produce strings and tables of numbers respectively. FCC is form constant
character, FCC "Hello" converts the characters HELLO into ASCII codes in
consecutive memory locations. FCB is form constant byte and is used to
produce constant or initial values into memory locations. FCB $04 sets
up the value $04 into the current memory location in the assembly process.
Q. I am also having
some trouble with the simulator program. Often it will tell me the file
does not exist when I try and load a program, Why is this?
A. A couple of reasons. If the assembly
process results in errors then no machine code will be produced ie no MYFILE.S19
to load into the simulator. The other case is that you might have saved
the file as MYFILE without an extension (*.asm), which means the assembler
can't find the file to begin with.
Q. Upon an interrupt
request (lets take RESET for instance), does the MPU load the address of
the first instruction to execute from the associated vector (memory locations)
into the PC? For the case of RESET these locations will be FFFE & FFFF.
A. Yes
Q. I cannot see
how the vectors for interrupts, which are defined in the program, find
their way into the respective MPU vector locations when the MPU and Memory
are clearly two different entities.
A. Remember the Vector locations ($FFF2-$FFFF)
are part of memory, typically in the ROM, and NOT part of the MPU itself.
Look at the interrupt program example on page 7.30 and 7.31.
Towards the end of the 'program' an ORG directive is
used for the vector area. Notice the FDB directives specifying addresses
in the program to fill the vectors. This is how it is normally done.
Q. In a similar
way the *.s19 (machine code) file also contains references to addresses
for RAM memory locations etc. As above, I am at loss to explain how these
constants end up in the RAM.
A. When
you use any 'code producing' directive such as FCB, FDB etc the bytes that
are generated from the data or addresses provided in the operand field
and become bytes in the *.S19 file, along with the program itself. Thus
when the program is downloaded so are the 'initialised' variables or tables.
This also include the vectors. This is done by the loader program.
Q. Another question
with regard to MC68000; It is said that MC68000 has 16M of addressable
space. Hence, 24 address lines (A0-A23). When looking at the pin-outs for
the MC68000, I find that there are only 23 lines (A1-A23) and this will
give only 8M. So the question is what happens to A0?
A. Take a look at the last paragraph and
table at the bottom of Appendix A page 3-4 in the data sheet for the MC68000.
Because of the 16 bit data bus width the standard size for a data move
is 2 bytes hence only down to A1 is required normally, but when we need
to access at a byte level the MC68000 provides separate UDS and LDS as
described in the data sheet.
Essentially LDS = inverse of A0 , UDS = A0. (Upper Data
Strobe and Lower Data Strobe)
Q. I had not realised
that it is mandatory (is it?) to place the (EP)ROM (or the program essentially)
at the high memory location (in the case of MC6809) so that the vectors
can reside at their proper place.
A. Yes this is typical of most micro's.
Q. I understand
that when the (EP)ROM is being programmed the programmer will get hold
of the *s.19 file and place the byte values at the corresponding address
locations.
A. This is correct, the programmer
loads all bytes created by the assembler and then you specify which area
you want to program into the EPROM. Typically the program itself is positioned
near the top of memory to include the interrupt vectors. Eg from $E000
to $FFFF. For this area to fit into an EPROM the EPROM would need to be
an 8K device.
Q. Assume a program
has variables starting at $0000 (in RAM) and an 8k (EP)ROM containing program
starting at $E000. Because the two devices (RAM & EPROM) only use address
lines A0 - A12 how come the microprocessor doesn't see them as the same
set of addresses.
A. The RAM and ROM are enabled at separate
address ranges say $0000 to $1FFF and $E000 to $FFFF. This is achieved
by address decoding circuits, see Module 9.
Only one of the devices is 'ON' or enabled at a time,
based on the address range. ie If the program accesses $0002 it turns on
the RAM, and if it accesses $E002 it turns on the ROM.
Q. Should
constants be stored in the ROM and variables stored in the RAM?
A. There are 2 cases, one for a development
system and one for a target system.
Development Sys - Constants, variables and program are usually placed where there is RAM so the machine code can be downloaded in the first place and so they can be changed if needed.
Target System - Assuming that they are true constants
(ie they don't get changed) they should be placed in the ROM. Variables
have to be in RAM but must be initialised in some way before you read a
value from them.
Back to 70635 Support Page