Introduction
The stack on the 6812 is an area of memory that is addressed by the stack pointer, sp. Data is placed on the stack with the use of a push instruction (psha, pshb, pshd, pshc). Keep in mind that the sp points to the last byte pushed onto the stack so when a push instruction is issued the sp must first decrease and then place the data into that memory location. Again decrease, store. The sp now points to the new top of the stack. The stack is grows towards low memory. Conversely when a pull instruction (pula, pulb, puld, pulc) is issued the data is pulled off the stack and placed in memory then the sp is increased. Sp is increased or decreased by 1 for acca, accb or the ccr (pula, pulb, pulc). Sp is increased or decreased by 2 for accd (pshd, puld) because accd is 2 bytes.
Subroutines are invoked with a jump to subroutine instruction (jsr). To end the subroutine the return from subroutine instruction (rts). After an rts the 6812 executed the instruction right after the jsr that called the subroutine.
Procedure
Part 0.
Connect the 6812 to the PC and hit the reset button. Do a rd in the comm window. What is the default value of the sp, stack pointer? If acca were to be pushed onto the stack right now what would be the new value of the sp?
Part 1.
Use rm in d-bug12 to initialize a,b,ix,iy to zero before running the program. Use t in d-bug12 to trace through this program line by line. Explain the result of each line. Notice that when acca is pushed onto the stack the sp is decremented first and then acca is put onto the stack. The instruction wai will push onto the stack the values of the registers.
org $800
lds #$85f
ldx #$c123
ldy #$c456
ldaa #$ca
ldab #$cb
psha
clra
pula
wai
Now examine the stack starting at $085f and explain the contents of the memory. Again what does the wai instruction do?
Part 2.
A Time delay is a common application for a subroutine. Here is an example. How many times is the dex instruction executed?
*main program 1
org $800
ldaa #$aa
jsr $delay
wai
*delay routine
delay ldx #$a
delay1 nop
nop
dex
bne delay1
rts
Loops can be nested to make a longer delay as shown in this next example.
*main program 2
portb equ 1
ddrb equ 3
org $800
movb #$ff,ddrb
ldaa #0
top staa portb
jsr delay
inca
jmp top
*delay routine
delay pshb
pshx
ldab #$2a
d2 ldx #$ffff
d1 dex
bne d1
decb
bne d2
pulx
pulb
rts
Another variation to achieve a long delay would be to write a delay routine that will delay for 1/100 second. Then call it 100 times from another subroutine.
*main program 3
...
jsr delay1 ;1 sec. delay
...
delay1 psha
ldaa #100 ;for 100 loops
delay1a jsr delay2 ; 1/100 sec. delay
deca
bne delay1a
pula
rts
delay2 pshx ;1/100 sec. delay routine
ldx #???? ;you calculate the value
delay2a nop
dex
bne delay2a
pulx
rts
Procedure for part 2. Connect port b to two 7447 and two 7 segment displays. Go to the comm window and make port b an output port and then send a number to port b. This will verify that the hardware is working. Hint:
mm 3, enter, ff, enter, .
mm 1, enter, 34, enter, .
If you send the #$34 to port b you will see a 34 on the display.
Type in one of the above programs. Make the delay for 1 second. Do a calculation of the time delay by counting the number of cycles in the delay routine and use the fact that the 6812 runs at 8 Mhz. Your main program is to do the following:
load acca w/ #1 infinite loop: store acca at port b delay for 1 sec. increment acca repeat
You must use subroutines. Run the program and notice how long the delay is. How does your calculation compare to the experimental measurement of the delay?
Part 3.
Modify the above program so that you display the numbers 00 to 59 like a clock. After 59 go back to 00 and repeat. Also change the delay so that it is very close to 1 second.