949 lines
22 KiB
Plaintext
949 lines
22 KiB
Plaintext
====================================================================
|
||
DR 6502 AER 201S Engineering Design 6502 Execution Simulator
|
||
====================================================================
|
||
|
||
Supplementary Notes By: M.J.Malone
|
||
|
||
|
||
Advanced 6502 Assembly Code Examples
|
||
====================================
|
||
|
||
The remainder of this file will be in a format acceptable to
|
||
TASM for direct assembly. Note there may be errors in the code, it
|
||
is not intended that it be cut up and included in students files.
|
||
It is meant only as an example of addressing modes and
|
||
instructions. The first example is a prime number finder. The
|
||
second example is a set of subroutines to maintain a multitasking
|
||
system.
|
||
|
||
|
||
;==============================================================================
|
||
; Advanced Coding Examples for the Students of AER201S
|
||
;==============================================================================
|
||
;
|
||
;
|
||
.ORG $E000
|
||
SEI ; INITIALIZING THE STACK POINTER
|
||
LDX #$FF
|
||
TXS
|
||
;
|
||
LDX #$00
|
||
LDY #$00
|
||
Delay DEX
|
||
BNE Delay
|
||
DEY
|
||
BNE Delay
|
||
;
|
||
;=============================================================================
|
||
; Prime Number Finder
|
||
;=============================================================================
|
||
; This Prime Number Finder uses the sieve method to find the primes up to 255
|
||
; and then uses those primes to find the primes up to 65535. Note that this
|
||
; is of course not THE most efficient way to find primes but it makes a good
|
||
; demonstration.
|
||
; It would be neat to stack this code up against a casually written/optimized
|
||
; compiled C prime number finder on a raging 386. I have a feeling there will
|
||
; be less than a factor of ten difference on execution speed. You may be
|
||
; surprised just how fast the 6502 is on simple problems.
|
||
;
|
||
Test_num = $00 ; Test Number to Eliminate non-primes
|
||
Array = $00 ; Base Address for the array of primes
|
||
;
|
||
;
|
||
lda #$01
|
||
sta $a003
|
||
lda #$01
|
||
sta $a001 ; Turns on an LED on bit zero of port A of VIA 1
|
||
; to let you know it has started looking for primes
|
||
;
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
page 2
|
||
|
||
ldx #$01 ; Initialize the array of numbers
|
||
Init_Loop txa
|
||
sta Array,x
|
||
inx
|
||
bne Init_loop
|
||
;
|
||
lda #$02 ; Initialize the Test_num = 2
|
||
sta Test_num
|
||
lda #$04 ; Put the square of 2 in the accumulator
|
||
; as the first non-prime
|
||
;
|
||
; Start Setting the Multiples of the Test_num to zero
|
||
Start_num
|
||
Got_Mult tax
|
||
stz Array,x ; Set multiples of Test_num to zero since they
|
||
clc ; are not prime.
|
||
adc Test_num ; Calculate the next multiple
|
||
bcs Next_num ; Until the Multiples are outside the array
|
||
jmp Got_Mult
|
||
;
|
||
Next_num inc Test_num ; Go on to the next Test_num
|
||
ldx Test_num
|
||
cpx #$10 ; Until Test_num => sqrt(largest number)
|
||
beq More_Primes
|
||
lda Array,x
|
||
beq Next_num ; Don't use Test_num if Test_num is not prime
|
||
txa
|
||
; Got a valid new Test_num, now find its square because all non-primes
|
||
; multiples less than its square are eliminated already
|
||
dex
|
||
clc
|
||
Square adc Test_num
|
||
dex
|
||
bne Square
|
||
; OK Got the square of Test_num in the accumulator
|
||
; lets start checking
|
||
jmp Start_num
|
||
;
|
||
;
|
||
More_Primes
|
||
;
|
||
; Ok now we have all the primes up to 255 in the memory locations $01-$FF
|
||
; Lets repack them more neatly into an array with no spaces to make our
|
||
; life easier
|
||
;
|
||
ldx #$00 ; .X is a pointer into the loose array
|
||
ldy #$01 ; .Y is a pointer into the packed array
|
||
Repack inx
|
||
beq Done_packing
|
||
lda Array,x
|
||
beq Repack
|
||
sta Array,y
|
||
iny
|
||
jmp Repack
|
||
;
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
page 3
|
||
|
||
Prime_Ptr = $F0 ; This is a points into the list of primes greater
|
||
; than $FF and less that $10000
|
||
;
|
||
Poss_Prime = $F2 ; Possible prime
|
||
Temp = $F4 ; A Temporary Number used to find modulus
|
||
Shift = $F6 ; Number of Places that .A is shifted
|
||
TempArg = $F7 ; A temporary number; argument of modulus
|
||
|
||
;
|
||
Done_packing
|
||
lda #$00 ; Store a $00 at the end of the array of short
|
||
sta Array,y ; primes so we know when we have reached the end
|
||
lda #$00
|
||
sta Prime_ptr ; Set the Prime Pointer (for primes >$FF)
|
||
lda #$02 ; pointing into $0200. The found primes will be
|
||
sta Prime_ptr+1 ; recorded sequentially from there on.
|
||
;
|
||
lda #$01 ; Start with $0101 as the first possible prime
|
||
sta Poss_Prime
|
||
sta Poss_Prime+1
|
||
;
|
||
Next_PP ldy #$02
|
||
Next_AP lda Array,y
|
||
beq Prime
|
||
jsr Mod
|
||
beq Next_Poss_prime ; it was a multiple of Array,y
|
||
; and therefore not prime
|
||
iny
|
||
jmp Next_AP
|
||
;
|
||
Prime ldx #$00
|
||
lda Poss_prime ; Store prime away in the array of primes
|
||
sta (Prime_ptr,x)
|
||
inx
|
||
lda Poss_prime+1
|
||
sta (Prime_ptr,x)
|
||
clc
|
||
lda Prime_ptr ; Increment the pointer in the array of primes
|
||
adc #$02
|
||
sta Prime_ptr
|
||
lda Prime_ptr+1
|
||
adc #$00
|
||
sta Prime_ptr+1
|
||
;
|
||
Next_Poss_prime
|
||
clc ; Increment Poss_Prime to look at the next
|
||
lda Poss_Prime ; number
|
||
adc #$01
|
||
sta Poss_Prime
|
||
lda Poss_Prime+1
|
||
adc #$00
|
||
sta Poss_Prime+1
|
||
bcc Next_PP ; Carry will be set when we reach $10000
|
||
;
|
||
; Ends when it has found all the primes up to 65535
|
||
;
|
||
;
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
page 4
|
||
|
||
lda #$00
|
||
sta $a001 ; Turns off the LED after the code finishes
|
||
;
|
||
DONE JMP DONE ; Endless loop at end to halt execution
|
||
;
|
||
;
|
||
;
|
||
; --------------------------------------------------------------------------
|
||
; Find the Modulus Remainder of Poss_Prime and number in A
|
||
; --------------------------------------------------------------------------
|
||
; Input Regs: .A Number being divided into the Possible Prime
|
||
; Poss_Prime contains the number being tested for primeness
|
||
; Output Regs: .A Modulo remainder
|
||
;
|
||
Mod ldx Poss_Prime ; Transfer Poss_Prime to Temp
|
||
stx Temp
|
||
ldx Poss_Prime+1
|
||
stx Temp+1
|
||
ldx #$00 ; Set the bit shifting counter to #$00
|
||
stx Shift
|
||
;
|
||
; Compare A to the upper byte of Temp
|
||
;
|
||
Compare sec ; Compare to see if the .A is greater than
|
||
cmp Temp+1 ; (equal to) the high byte of Temp
|
||
bcs A_Bigger
|
||
;
|
||
; If the accumulator is smaller than the upper byte of Temp then shift it
|
||
; until it is bigger or it overflows the highest bit
|
||
;
|
||
clc
|
||
rol a
|
||
bcc Not_off_end
|
||
;
|
||
; It has overflowed the highest bit, unroll it by one position
|
||
;
|
||
ror a
|
||
sta TempArg
|
||
jmp Start_Mod
|
||
;
|
||
; Not overflowed yet, go and compare it to Temp+1 again
|
||
;
|
||
Not_off_end inc Shift
|
||
jmp Compare
|
||
;
|
||
; If the accumulator is bigger and it has been shifted then unshift by one
|
||
; bit
|
||
;
|
||
A_Bigger ldx Shift
|
||
cpx #$00
|
||
sta TempArg
|
||
beq Start_Mod
|
||
clc
|
||
ror a
|
||
dec Shift
|
||
sta TempArg
|
||
;
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
page 5
|
||
|
||
; If the accumulator was smaller than the highest byte of Temp it now
|
||
; has been shifted to strip off the high bit at least
|
||
; If the accumulator was larger than the highest byte then proceed with the
|
||
; regular modulus shift and subtracts
|
||
;
|
||
Start_Mod lda Temp+1
|
||
sec
|
||
cmp TempArg
|
||
bcc Dont_Subt
|
||
;
|
||
; Subtract as a stage of division
|
||
;
|
||
sbc TempArg
|
||
sta Temp+1
|
||
;
|
||
Dont_Subt
|
||
;
|
||
; We would now like to shift the TempArg relative the Temp
|
||
; 1) Shift is greater than zero - accumulator was shifted - unshift it
|
||
; 2) Shift Temp - if shift reaches -8 then we are out of Temp and
|
||
; what we have left is the modulus --RTS
|
||
;
|
||
lda Shift
|
||
bmi Sh_Temp ; Case 2
|
||
beq Sh_Temp
|
||
; Case 1
|
||
clc
|
||
ror TempArg
|
||
dec Shift
|
||
jmp Start_Mod
|
||
;
|
||
Sh_Temp cmp #$f8
|
||
bne Continue
|
||
lda Temp+1 ; This is the Modulus
|
||
rts
|
||
|
||
Continue dec Shift
|
||
clc
|
||
rol Temp
|
||
rol Temp+1
|
||
jmp Start_Mod
|
||
;
|
||
.ORG $FFFC
|
||
.WORD $E000
|
||
.END
|
||
;
|
||
;
|
||
;
|
||
;==============================================================================
|
||
;******************************************************************************
|
||
;==============================================================================
|
||
;
|
||
;
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
page 6
|
||
|
||
;=============================================================================
|
||
; The Multitasking 6502 - See you 6502 do several things at once
|
||
;=============================================================================
|
||
; This relies on the assumption that there is a source of IRQ's out there
|
||
; that is repetitive and each task is allotted time between each IRQ.
|
||
; Process 1 is started automatically by the RESET signal.
|
||
; Any process can extend its life for a while (if it is doing something
|
||
; important) by setting the SEI and then CLI after the important section.
|
||
;
|
||
;
|
||
;
|
||
.ORG $E000
|
||
SEI ; INITIALIZING THE STACK POINTER
|
||
LDX #$FF
|
||
TXS
|
||
;
|
||
LDX #$00
|
||
LDY #$00
|
||
Delay DEX
|
||
BNE Delay
|
||
DEY
|
||
BNE Delay
|
||
;
|
||
; Each Process has a reserved space in memory starting with process 1 at
|
||
; $0200-$03FF, process 2 at $0400-$05FF. With this model, an 8K RAM can
|
||
; support 15 such processes provided none of the RAM outside zero page and
|
||
; stack is used during the execution of a particular process.
|
||
;
|
||
M_box = $F0 ; A Mailbox used to communicate between processes
|
||
Com1 = $F8 ; User Communications Channel to other processes
|
||
Com2 = $F9
|
||
Temp = $FA ; A temporary variable used during SWAPS and SPAWNS
|
||
Proc_Ptr = $FB ; Pointer to the reserved space of the current process
|
||
Proc = $FC ; Current process number
|
||
Proc_N = $FE ; Actual Number for active Processes
|
||
Proc_M = $FF ; Maximum Number of Processes that have been concurrent
|
||
;
|
||
; A Process Record Consists of:
|
||
; Offset Purpose
|
||
; ------ -------
|
||
; 00 Priority
|
||
; 01 Priority Counter
|
||
; 02 Accumulator
|
||
; 03 X Register
|
||
; 04 Y Register
|
||
; 05 Stack Pointer
|
||
;
|
||
; 10-FF Zero Page Memory from $00-$EF
|
||
; 100-1FF System Stack Space
|
||
;
|
||
lda #$01 ; Initialize the start up process as 1
|
||
sta Proc
|
||
sta Proc_N ; Set the number of processes to 1
|
||
sta $0200 ; Set the priority of process 1 to 1
|
||
lda #$00
|
||
sta $0201 ; Set the priority counter of process 1 to 0
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
page 7
|
||
|
||
lda #$00
|
||
sta Proc_Ptr ; Initialize the process pointer to point to
|
||
lda #$02 ; Process 1 reserved space $0200-$03FF
|
||
sta Proc_Ptr+1
|
||
JMP Start_Code
|
||
;
|
||
;===========================================================================
|
||
; IRQ Subroutine to Swap Tasks
|
||
;===========================================================================
|
||
;
|
||
IRQ_VECT sta Temp ; Store .A Temporarily
|
||
;
|
||
; If there is only one active process currently then just return
|
||
;
|
||
lda Proc_N
|
||
cmp #$01
|
||
bne Cont_Swap1
|
||
lda Temp
|
||
rti
|
||
;
|
||
; Continue there is more than one Process
|
||
;
|
||
Cont_Swap1 tya
|
||
pha
|
||
;
|
||
; Check process priority counter. If it equals the priority of the process
|
||
; then attempt to swap in another process
|
||
;
|
||
ldy #$00
|
||
lda (Proc_Ptr),y ; Load Priority Number
|
||
beq Swap_In ; If 'killed' process then just swap in another
|
||
iny
|
||
inc (Proc_Ptr),y ; Increment Priority Counter
|
||
cmp (Proc_Ptr),y
|
||
beq Cont_Swap2
|
||
;
|
||
; Not done this Process, Return
|
||
;
|
||
pla
|
||
tay
|
||
lda Temp
|
||
rti
|
||
;
|
||
; Other Processes available and this one is done: S W A P O U T
|
||
;
|
||
Cont_Swap2 pla
|
||
ldy #$04
|
||
sta (Proc_Ptr),y ; Save .Y
|
||
dey
|
||
txa
|
||
sta (Proc_Ptr),y ; Save .X
|
||
dey
|
||
lda Temp
|
||
sta (Proc_Ptr),y ; Save .A
|
||
ldy #$05
|
||
tsx
|
||
txa
|
||
sta (Proc_Ptr),y ; Save .SP
|
||
|
||
|
||
|
||
|
||
|
||
|
||
page 8
|
||
|
||
;
|
||
; Swap Zero Page ($00-$EF) to (Proc_Ptr + $10-$FF)
|
||
;
|
||
ldy #$00
|
||
lda #$10
|
||
sta Proc_Ptr
|
||
Out_Zero lda $00,y
|
||
sta (Proc_Ptr),y
|
||
iny
|
||
cpy #$f0
|
||
bne Out_Zero
|
||
;
|
||
; Swap System Stack
|
||
;
|
||
lda #$00
|
||
sta Proc_Ptr
|
||
inc Proc_Ptr+1
|
||
tsx
|
||
txa
|
||
tay
|
||
Out_Stack iny
|
||
beq Swap_In
|
||
lda $0100,y
|
||
sta (Proc_Ptr),y
|
||
jmp Out_Stack
|
||
;
|
||
;
|
||
; Look for the next process to swap in
|
||
;
|
||
Swap_In
|
||
Another lda Proc ; Looking for another process to Swap in
|
||
cmp Proc_M
|
||
bne Not_End
|
||
;
|
||
; Go back to Process #1
|
||
;
|
||
lda #$01
|
||
sta Proc
|
||
lda #$02
|
||
sta Proc_Ptr+1
|
||
jmp Check_Proc
|
||
;
|
||
; Go to the next Process
|
||
;
|
||
Not_End clc
|
||
lda Proc_Ptr+1
|
||
adc #$02
|
||
sta Proc_Ptr+1
|
||
inc Proc
|
||
;
|
||
; Check this Process if Non-Active, go try another
|
||
;
|
||
ldy #$00
|
||
lda (Proc_Ptr),y
|
||
beq Another
|
||
;
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
page 9
|
||
|
||
; Found an Acceptable Process: S W A P I N
|
||
;
|
||
;
|
||
; Get the Stack Pointer
|
||
;
|
||
ldy #$05
|
||
lda (Proc_Ptr),y ; Restore .SP
|
||
tax
|
||
txs
|
||
;
|
||
; Swap In Zero Page ($00-$EF) to (Proc_Ptr + $10-$FF)
|
||
;
|
||
ldy #$00
|
||
lda #$10
|
||
sta Proc_Ptr
|
||
In_Zero lda (Proc_Ptr),y
|
||
sta $00,y
|
||
iny
|
||
cpy #$f0
|
||
bne In_Zero
|
||
;
|
||
; Swap System Stack
|
||
;
|
||
lda #$00
|
||
sta Proc_Ptr
|
||
inc Proc_Ptr+1
|
||
tsx
|
||
txa
|
||
tay
|
||
In_Stack iny
|
||
beq Restore_Regs
|
||
lda (Proc_Ptr),y
|
||
sta $0100,y
|
||
jmp In_Stack
|
||
;
|
||
; Restore all of the system registers
|
||
;
|
||
Restore_Regs
|
||
lda #$00
|
||
sta Proc_Ptr
|
||
dec Proc_Ptr+1
|
||
ldy #$01 ; Set Priority Counter to 0
|
||
sta (Proc_Ptr),y
|
||
iny
|
||
lda (Proc_Ptr),y ; Temporarily store .A
|
||
sta Temp
|
||
iny
|
||
lda (Proc_Ptr),y ; Restore .X
|
||
tax
|
||
iny
|
||
lda (Proc_Ptr),y ; Restore .Y
|
||
tay
|
||
lda Temp ; Restore .A
|
||
rti
|
||
;--------------------- Done the Swap ----------------------
|
||
;
|
||
;
|
||
;
|
||
|
||
|
||
|
||
|
||
|
||
|
||
page 10
|
||
|
||
;==========================================================
|
||
; Spawn a New Process
|
||
;==========================================================
|
||
; PHA Process PCH
|
||
; PHA Process PCL
|
||
; PHA Process Priority
|
||
; JSR Spawn High
|
||
; Spawn Low
|
||
;
|
||
;
|
||
Spawn lda Proc_Ptr+1 ; Store Current Process Pointer
|
||
sta Temp
|
||
lda Proc ; Store Current Process Number
|
||
pha
|
||
lda #$01 ; Set Process Pointer and Number to 1
|
||
sta Proc
|
||
lda #$02
|
||
sta Proc_Ptr+1
|
||
;
|
||
Free_Check ; See if there is an old process number no longer
|
||
ldy #$00 ; in use
|
||
lda (Proc_Ptr),y
|
||
beq Got_Free
|
||
inc Proc
|
||
clc
|
||
lda Proc_Ptr+1
|
||
adc #$02
|
||
sta Proc_Ptr+1
|
||
lda Proc_M
|
||
sec
|
||
cmp Proc
|
||
bcs Free_Check
|
||
inc Proc_M ; Have to create an extra Process
|
||
inc Proc_N
|
||
;
|
||
; Ok we are clear, Create this Process
|
||
;
|
||
Got_Free tsx ; Get the current stack pointer
|
||
txa
|
||
clc
|
||
adc #$05
|
||
tax ; Set x to point at Priority
|
||
;
|
||
ldy #$00
|
||
lda $0100,x ; Transfer Priority to Process Space
|
||
sta (Proc_Ptr),y
|
||
;
|
||
ldy #$05 ; Set .sp = #$FC
|
||
lda #$FC
|
||
sta (Proc_Ptr),y
|
||
;
|
||
ldy #$02 ; Set the accumulator to 1 to indicate: START
|
||
lda #$01 ; to the new process
|
||
sta (Proc_Ptr),y
|
||
;
|
||
inc Proc_Ptr+1 ; To point into stack swap space for this process
|
||
;
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
page 11
|
||
|
||
lda #$00 ; Processor Status Register, for this process
|
||
ldy #$FD
|
||
sta (Proc_Ptr),y
|
||
;
|
||
inx
|
||
lda $0100,x ; Load PCL
|
||
iny
|
||
sta (Proc_Ptr),y ; Put into (swapped) Stack
|
||
;
|
||
inx
|
||
lda $0100,x ; Load PCH
|
||
iny
|
||
sta (Proc_Ptr),y ; Put into (swapped) Stack
|
||
;
|
||
lda Temp ; Set Pointer back to original (Spawner) process
|
||
sta Proc_Ptr+1
|
||
;
|
||
lda Proc ; Take Spawned Process number and put in Temp
|
||
sta Temp
|
||
;
|
||
pla ; Restore Spawned Process number
|
||
sta Proc
|
||
;
|
||
pla ; Pull 'Spawn' return address from stack
|
||
tax
|
||
pla
|
||
tay
|
||
;
|
||
pla ; Pull Spawn data out of the stack
|
||
pla
|
||
pla
|
||
;
|
||
tya ; Push the Return Address back to the stack
|
||
pha
|
||
txa
|
||
pha
|
||
lda Temp ; Return Spawned Process Number
|
||
rts
|
||
;-------------- Done Spawn -----------------
|
||
;
|
||
;
|
||
;
|
||
;=============================================================
|
||
; Kill a Process
|
||
;=============================================================
|
||
;
|
||
; Input Registers : NONE
|
||
; Output Registers: NEVER RETURNS IF KILL IS SUCCESSFUL
|
||
;
|
||
Kill lda Proc_N
|
||
cmp #$01 ; Can't Clear Last Process
|
||
bne Ok_More
|
||
rts
|
||
Ok_More ldy #$00 ; OK Kill the Process, put a 0 in Priority
|
||
tya
|
||
sta (Proc_Ptr)
|
||
;
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
page 12
|
||
|
||
dec Proc_N ; One Less Process
|
||
;
|
||
lda Proc ; If we are clearing 'Maximum' Process then
|
||
cmp Proc_M ; then reduce maximum
|
||
beq Reduce_Max
|
||
jmp Swap_In ; Otherwise Go swap another in
|
||
;
|
||
Reduce_Max
|
||
dec Proc
|
||
dec Proc_M
|
||
dec Proc_Ptr+1
|
||
dec Proc_Ptr+1
|
||
lda (Proc_ptr),y
|
||
beq Reduce_Max
|
||
jmp Swap_In
|
||
;---------------------- Done Clear a Process ---------------------------
|
||
;
|
||
;
|
||
;
|
||
;
|
||
;=======================================================================
|
||
; An Example Spawnable Process
|
||
;=======================================================================
|
||
; Input Registers: .A = #$00 Means that we just want the address of
|
||
; (JSR Child) this process so that the process swapper
|
||
; will know where to start.
|
||
;
|
||
; (RTI to CHILD1) .A = #$01 Means that the process swapper has signalled
|
||
; this process to actually start
|
||
;
|
||
Child jsr Child1
|
||
Child1 cmp #$00
|
||
bne Go_For_It
|
||
;
|
||
; Process was called to get its start up address
|
||
;
|
||
pla ; Grab Child1 start up address
|
||
clc
|
||
adc #$01 ; Remember that an RTS return address points at the
|
||
tax ; last byte of the JSR statement.
|
||
pla ; RTI return addresses point to the first byte of the
|
||
adc #$00 ; next instruction to be executed
|
||
tay
|
||
;
|
||
pla ; Save Return Address to program calling Child
|
||
sta Temp
|
||
pla
|
||
sta Proc_Ptr
|
||
;
|
||
tya ; Push Child1 RTI address
|
||
pha
|
||
txa
|
||
pha
|
||
;
|
||
lda Proc_Ptr ; This Pushes the calling program's return address
|
||
pha ; back into the stack
|
||
lda Temp
|
||
pha
|
||
;
|
||
|
||
|
||
|
||
|
||
|
||
page 13
|
||
|
||
lda #$00 ; Returns Proc_Ptr(low) to #$00 after its use as a
|
||
sta Proc_Ptr ; Temporary variable
|
||
rts
|
||
;
|
||
; Spawned Process actually starts:
|
||
; Note that PLA's are not required to get rid of the JSR Child1 start up
|
||
; address since the RTI address pushed in points to Child1 NOT Child
|
||
Go_For_It
|
||
|
||
Body of the spawned process
|
||
|
||
;
|
||
;
|
||
;=======================================================================
|
||
; An Example of a Kill of the present Process
|
||
;=======================================================================
|
||
;
|
||
{ User Code }
|
||
;
|
||
sei
|
||
jsr Kill ; This should kill the process unless it is the
|
||
; only process
|
||
cli
|
||
;
|
||
; This is the only process
|
||
;
|
||
{ More user code }
|
||
;
|
||
;
|
||
;
|
||
;=======================================================================
|
||
; Start of User Code
|
||
;=======================================================================
|
||
Start_Code
|
||
{ Your first process goes here }
|
||
;
|
||
;
|
||
; Example Spawn of Process 'Child'
|
||
;
|
||
sei ; Prevent swap attempts during process creation
|
||
lda #$00
|
||
jsr Child ; Request Address for Child1
|
||
;
|
||
lda #Priority
|
||
pha ; Push Priority into the stack
|
||
;
|
||
jsr Spawn ; Ask the Process Swapper to set 'Child1' up in
|
||
; the swap schedule
|
||
rol a
|
||
sta Ptr+1 ; Set pointer to the Child process zero page
|
||
lda #$10 ; reserved area
|
||
sta Ptr
|
||
;
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
page 14
|
||
|
||
; The Spawn call returns the process number. If there is some initial data
|
||
; or a pointer that this process would like to pass to 'Child1' then the
|
||
; address of its ZERO PAGE reserved data space is pointed to by '(Ptr),y'.
|
||
; Once the data has been transferred:
|
||
;
|
||
cli ; Re-enable swap attempts
|
||
;
|
||
;
|
||
;
|
||
;============================================================================
|
||
; Example of Taking full control of execution temporarily
|
||
;============================================================================
|
||
;
|
||
sei ; Disable swaps
|
||
{ User Code }
|
||
cli ; Re-enable swaps
|
||
;
|
||
;
|
||
;
|
||
;============================================================================
|
||
; Example of taking full control by Killing all other processes
|
||
;============================================================================
|
||
;
|
||
Ptr = $00
|
||
K_Proc = $02
|
||
;
|
||
sei ; Disable swaps
|
||
;
|
||
lda #$00 ; Set Pointer to $0200
|
||
sta Ptr
|
||
lda #$02
|
||
sta Ptr+1
|
||
;
|
||
lda #$01 ; Set Kill Process counter to 1
|
||
sta K_Proc
|
||
;
|
||
Top lda Proc
|
||
cmp K_Proc
|
||
beq Don_t_Kill
|
||
ldy #$00
|
||
tya
|
||
sta (Ptr),y
|
||
;
|
||
Don_t_Kill
|
||
cmp Proc_M
|
||
beq Done_Kill
|
||
inc Ptr+1
|
||
inc Ptr+1
|
||
inc K_Proc
|
||
jmp Top
|
||
;
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
page 15
|
||
|
||
Done_Kill
|
||
lda #$01
|
||
sta Proc_N
|
||
lda Proc
|
||
sta Proc_M
|
||
cli ; Note that this is optional, if we know that there
|
||
; are no other processes we could prevent swap decisions
|
||
; by not clearing the IRQ mask.
|
||
;
|
||
{ More code that will not be swapped out }
|
||
;
|
||
;
|
||
;
|
||
.ORG $FFFC
|
||
.WORD $E000
|
||
.WORD IRQ_VECT
|
||
.END
|
||
;
|
||
; -------------------- Done Multitasking example -------------------------
|
||
|
||
<eof>
|
||
|