Combined stack and stackx modules, updated documentation and test program

This commit is contained in:
Curtis F Kaylor 2020-10-19 22:44:24 -04:00
parent 85b04dff00
commit 414d673db5
6 changed files with 449 additions and 581 deletions

View File

@ -1,141 +1,172 @@
Sta Functions
This module contains functions to access and manipulate a stack structure.
The entries on a stack are stored in contiguous bytes of memory.
This module contains functions to access and manipulate a stack
of multi-byte entries stored in a contiguous section of memory.
Each element of the stack can vary in size from 1 to 255 bytes. Both
arrays and strings may be pushed onto and pulled off the stack.
Each entry of the stack consists of 1 to 255 bytes of data
followed by a single byte containing the number of data bytes,
allowing entries to be of different sizes. Entries may be
arrays, strings, or structs.
Usage: at the beginning of the program use the directives
#include <stddef.h02>
#include <memory.h02>
#include <string.h02>
#include <stack.h02>
The following application variables are defined:
int stkbgn Stack Begin: Address of the start of the stack.
int stkend Stack End: Address of the end of the stack.
zeropage int stkptr Stack Pointer: Current position in the stack.
The variables stkbgn and stkend must be set
before calling any functions. A program can
use multiple stacks by saving and restoring
stkbgn, stkend, and stkptr.
The following application functions are defined:
stkbgn(&b); Stack Begin: Sets the beginning of the stack
to address b.
The beginning of a stack is the first byte
of memory in the stack space.
Although stack space usually begins on a 256
byte boundary, this is not required.
Note: Sets variables stkslo and stkshi.
stkend(&e); Stack End: Sets the end of the stack to address
e. The end of a stack is the byte after the last
byte of memory in the stack space.
Although stack space usually ends on a 256
byte boundary, this is not required.
Note: Sets variables stkelo and steshi.
stkrst(); Stack Reset: Set stack pointer to stack begin
address.
This routine is called before populating a
stack with calls to the stkpsh function.
The first time s stack is used, this routine
must be called after setting the variables
stkbgn and stkend and before calling any other
stack functions.
r = stkpsh(n ,&m); Stack Push: Creates a new entry at the end of
the stack consisting of n bytes of array m.
This routine can also be called to deallocate
all entries, effectively clearing the stack.
If n is 0 or the new entry would overflow the
end of the stack space, no entry is created and
a value of 0 is returned. Otherwise, the number
of bytes in the new entry is returned.
Note: Sets stkptr to stkbgn.
Note: Sets dstlo and dsthi to stkslo and stkhi
prior to the copy, updates stkslo and stkshi,
then calls the memcpy function.
r = stkpop(&m); Stack Pop: Copies the bytes from the last entry of
the stack into array m and removes the entry from
the stack.
If the stack is empty, the value 0 is returned.
Otherwise, the number of bytes in the popped entry
is returned.
Note: Sets dstlo and dsthi to the address of m,
updates stklo and stkhi to point to the beginning
of the last entry, sets srclo and srchi to stklo
and stkhi, then calls the memcpy function.
r,m,l = stksiz(); Stack Size: Calculates and returns the current size
r,i = stksiz(); Stack Size: Calculates and returns the current size
of the stack along with a flag indicating whether
the stack is populated or empty.
The first byte returned will be 255 (True) if the
Returns a char, which will be 255 (True) if the
stack contains at least one entry, or 0 (False) if
the stack is empty. The second and third returned
bytes are the size of the stack as a sixteen bit
number, most-significant and least-significant byte,
respectively.
the stack is empty, and int which is the size of
the stack.
Note: Subtracts the sixteen bit value contained in
stkslo and stkhi from the value in stklo and stkhi.
Note: Subtracts stkbgn from stkptr.
r = stkpsh(n,m); Stack Push: Creates a new entry at the end of
the stack consisting of n bytes of array m.
Returns zero if n is 0 or an overflow would
occur. Otherwise, returns the the size of the
new entry.
Note: Sets srcptr to &m, dstptr to stkptr,
updates stkptr, then calls memcpy().
r = stkstr(s); Stack String: Creates a new entry at the end of
the stack consisting the characters in string
s, including the terminating ASCII null. This
ensures that when the entry is popped off the
stack, the destination string will be properly
terminated.
Returns zero if s is empty or an overflow would
occur. Otherwise, returns the the size of the
new entry.
Note: Calls strlen(), then calls stkpsh().
r = stkdup(); Stack Duplicate: Creates a new entry at the end
of the stack consisting of the bytes in the last
entry of the stack.
Returns zero if the stack is empty or an overflow
would occur. Otherwise, returns the the size of
the new entry.
Note: Sets dstptr to stkptr, sets srcptr to the
beginning of the last entry, updates stkptr,
then calls memcpy().
r = stkovr(); Stack Over: Creates a new entry at the end of
the stack consisting of the bytes in the second
to last entry of the stack.
Returns zero if the stack has less than two
entries or an overflow would occur. Otherwise,
returns the the size of the new entry.
Note: Sets dstptr to the stkptr and srcptr to
the beginning of the second to last entry,
updates stkptr then calls the memcpy().
r = stkswp(); Stack Swap: Moves the last entry in the stack to
the second to last position and the second to
last entry to the last position.
Returns zero if the stack has less than two
entries or an overflow would occur. Otherwise,
returns the the size of the new last entry.
Note: Saves stkptr, calls stkovr(), restores
stkptr, then calls memcpy() twice.
r = stktop(m); Stack Top: Copies the bytes from the last entry
of the stack into array m and leaves the entry
on the stack.
Returns zero if the stack is empty. Otherwise,
returns the the size of the new entry.
Note: Saves stkptr, calls stkpop(), then restores
stkptr.
r = stkpop(m); Stack Pop: Copies the bytes from the last entry
of the stack into array m and deallocates the
entry from the stack.
If the stack is empty, the value 0 is returned.
Otherwise, the number of bytes in the popped
entry is returned.
Note: Sets dstptr to &m, sets stkptr to the
beginning of the last entry, sets srcptr to
stkptr, then calls the memcpy().
r = stkdrp(); Stack Drop: Deallocates the last entry from the
stack.
If the stack is empty, the value 0 is returned.
Otherwise, the number of bytes in the dropped
entry is returned.
Note: Sets dstptr to &m, sets stkptr to the
beginning of the last entry, sets srcptr to
stkptr, then calls the memcpy().
The following utility functions are not normally used in applications:
*,m,l = stkptr(); Stack Pointer: Returns the address contained in
the stack pointer as the most significant byte
and the least significant byte.
Note: Reads variables stklo and stkhi.
stkset(&d); Stack Set: Sets stack pointer to address d.
Note: Sets variables stklo and stshi.
stkadd(b); Stack Add: Increases the stack pointer by b.
Note: Updates variables stklo and stshi.
stksub(b); Stack Subtract: Decreases the stack pointer by b.
Note: Updates variables stslo and stshi.
stkinc(b); Stack Increment: Increases the stack pointer by 1.
Note: Updates variables stklo and stshi.
stkdec(b); Stack Decrement: Secreases the stack pointer by 1.
Note: Updates variables stslo and stshi.
stkssp(); Save Stack Pointer: Copies contents of the stack
pointer to variables temp1 and temp2.
Note: Calls stkptr() then savrxy().
stkrsp(); Restore Stack Pointer: Copies contents of variables
temp1 and temp2 to the stack pointer.
Note: Calls resrxy() then stkset().
Note: This module expects the following functions to be defined
memcpl Copy memory (alternate entry point)
memcpy Copy memory
ressrc Restore source pointer
resrxy Restore X and Y registers
savrxy Save X and Y registers
setdst Set destination pointer
setsrc Set source pointer and initialize index
setsrc Set source pointer
strlen Get string Length
along with the zero page variable pairs
along with the zero page integer variables
srclo, srchi Source String Pointer
dstlo, dsthi Destination String Pointer
stklo, stkhi stack Pointer
srcptr Source String Pointer
dstptr Destination String Pointer
stkptr stack Pointer
the static variables
the static integer variables
stkslo, stkshi Stack Start Address
stkelo, stkehi Stack End Address
stkbgn Stack Start Address
stkend Stack End Address
and the transient variables

View File

@ -1,244 +1,286 @@
;C02 stack module assembly language subroutines
;Requires external zero page variables
;STKLO, STKHI, DSTLO, DSTHI, SRCLO, SRCHI
;external variables
;STKSLO, STKSHI, STKELO, STKEHI, TEMP0, TEMP1, TEMP2
;external routines
;MEMCPL, SETDST, SETSRC
;Requires external zero page words DSTPTR, SRCPTR, STKPTR,
;words STKBGN, STKEND, and bytes TEMP0, TEMP1, TEMP2 (header)
;and external routines RESRXY, SAVRXY, SETDST, SETSRC (stddef),
;MEMCPL (memory), and STRLEN (string)
;Implementation Notes:
;Stack starts at STKSLO,STKSHI and builds upward tp STKELO, STKEHI
;Stack starts at STKBGN and builds upward to STKEND
;Each entry on the stack consists of the entry data followed
;by a single byte containing the length of the entry data
;stkbgn(&b) - Set Stack Start Address
;Args: X,Y = Address
;Sets: STKSLO, STKSHI = Stack Start Address
;Affects: Z, N
STKBGN: STX STKSLO ;Save Stack Start LSB
STY STKSHI ;Save Stack Start MSB
RTS
SUBROUTINE STACK
;stkend(&b) - Set Stack End Address (+1)
;Args: X,Y = Address
;Sets: STKELO, STKEHI = Stack End Address
;Affects: Z, N
STKEND: STX STKELO ;Save Stack End LSB
STY STKEHI ;Save Stack End MSB
RTS
;stkptr() - Get Stack Pointer
;Uses: STKLO,STKHI = Stack Pointer
;Get Stack Pointer
;Affects: N,Z
;Returns: X = Stack Pointer LSB
; Y = Stack Pointer MSB
STKPTR: LDX STKLO ;Load Stack Pointer LSB
LDY STKHI ;Load Stack Pointer MSB
.GETPTR LDX STKPTR ;Load Stack Pointer LSB
LDY STKPTR+1 ;Load Stack Pointer MSB
RTS
;stkssp() - Save Stack Pointer
;Uses: STKLO,STKHI = Stack Pointer
;Sets: TEMP1.TEMP2 = Stack Pointer
;Save Stack Pointer
;Sets: TEMP1,TEMP2 = STKPTR
;Affects: N,Z
;Returns: X = Stack Pointer LSB
; Y = Stack Pointer MSB
STKSSP: JSR STKPTR ;Get Stack Pointer
JMP SAVRXY ;Save in TEMP1, TEMP2
.SAVPTR JSR .GETPTR ;Get Stack Pointer
JMP SAVRXY ;Save in TEMP1, TEMP2
;stksrc() - Set Source Pointer to Stack Pointer
;Uses: STKLO,STKHI = Stack Pointer
;Sets: SRCLO,SRCHI = Source Array Pointer
;.STKSRC() - Set Source Pointer to Stack Pointer
;Sets: SRCPTR = STKPTR
;Affects: X,N,Z
;Returns: Y = 0
STKSRC: JSR STKPTR ;Get Stack Pointer Address
JMP SETSRC ;Set Source/ an/d Return
.STKSRC JSR .GETPTR ;Get Stack Pointer Address
JMP SETSRC ;Set Source/ an/d Return
;stkdst() - Set Destination Pointer to Stack Pointer
;Uses: STKLO,STKHI = Stack Pointer
;Sets: DSTLO,DSTHI = Destination Array Pointer
;.STKDST() - Set Destination Pointer to Stack Pointer
;Uses: STKPTR = Stack Pointer
;Sets: DSTPTR = Destination Array Pointer
;Affects: N,Z
;Returns: X = Stack Pointer LSB
; Y = Stack Pointer MSB
STKDST: JSR STKPTR ;Get Stack Pointer Address
JMP SETDST ;Set Destination and Return
.STKDST JSR .GETPTR ;Get Stack Pointer Address
JMP SETDST ;Set Destination and Return
;stkrst() - Reset Stack Pointer to Start Address
;Uses: STKSLO, STKSHI = Stack Start Address
;Sets: STKLO, STKHI = Stack Pointer
;Uses: STKBGN = Stack Start Address
;Sets: STKPTR = Stack Pointer
;Affects: Z, N
;Returns: X = Stack Pointer LSB
; Y = Stack Pointer MSB
STKRST: LDX STKSLO ;Load X with Stack Start LSB
LDY STKSHI ;Load X with Stack Start MSB
JMP STKSET ;Store in Stack Pointer
STKRST: LDX STKBGN ;Load X with Stack Start LSB
LDY STKBGN+1 ;Load X with Stack Start MSB
JMP .SETPTR ;Store in Stack Pointer
;stkrsp() - Restore Stack Pointer
;.RESPTR() - Restore Stack Pointer
;Uses: TEMP1.TEMP2 = Stack Pointer
;Sets: STKLO,STKHI = Stack Pointer
;Sets: STKPTR = Stack Pointer
;Affects: N,Z
;Returns: X = Stack Pointer LSB
; Y = Stack Pointer MSB
STKRSP: JSR RESRXY ;Get TEMP1, TEMP2
;and fall into STKSET
.RESPTR JSR RESRXY ;Get TEMP1, TEMP2
;and fall into .SETPTR
;stkset() - Set Stack Pointer Address
;Args: X,Y = Address
;Sets: STKLO, STKHI = Stack Pointer Address
;Affects: Z, N
;Returns: X = Stack Pointer LSB
; Y = Stack Pointer MSB
STKSET: STX STKLO ;Store X in Stack Pointer LSB
STY STKHI ;Store Y in Stack Pointer MSB
RTS ;Exit Routine
;Set STKPTR to Y,X
.SETPTR STX STKPTR ;Store X in Stack Pointer LSB
STY STKPTR+1 ;Store Y in Stack Pointer MSB
RTS ;Exit Routine
;stkpsh(n, &m) - Push n Bytes of m onto Stack
;Args: A = Number of Bytes to Append
; Y,X = Address of Source Array
;Uses: STKELO, STKEHI = Stack End Address
;Sets: DSTLO, DSTHI = Pointer to Stack Entry
; SRCHI, SRCLO = Pointer to Source Array
;Uses: STKEND = Stack End Address
;Sets: DSTPTR = Pointer to Stack Entry
; SRCPTR = Pointer to Source Array
; TEMP0 = Number of Bytes to Append
;Updates: STKLO, STKHI = Stack Pointer
;Updates: STKPTR = Stack Pointer
;Returns: A=Number of Bytes Pushed
; 0 = Error: Stack Underflow
STKPSH: JSR SETSRC ;Set Source Address
STKPSA: STA TEMP0 ;Save Number of Bytes
JSR STKDST ;Set Destination to Stack Pointer
JSR STKALC ;Allocate Space on Stack
JMP MEMCPL ;Copy Bytes and Return
STKPSH: JSR SETSRC ;Set Source Address
.STKPSH STA TEMP0 ;Save Number of Bytes
JSR .STKDST ;Set Destination to Stack Pointer
JSR .ALLOC ;Allocate Space on Stack
JMP MEMCPL ;Copy Bytes and Return
;stkadd(n) - Add N Bytes to Stack Pointer
;Args: A=Number of Bytes to Allocate
;Updates: STKLO, STKHI = Stack Pointer
;Affects: A,C,N,Z
STKADD: CLC
STKADC: ADC STKLO ;Add to Stack Pointer LSB
STA STKLO ;and Save
LDA STKHI ;Add Carry
;Add A to STKPTR
.ADDPTR CLC
.ADCPTR ADC STKPTR ;Add to Stack Pointer LSB
STA STKPTR ;and Save
LDA STKPTR+1 ;Add Carry
ADC #0 ;to Stack Pointer MSB
STA STKHI ;and Save
STA STKPTR+1 ;and Save
RTS
;stkalc(n) - Allocate Space on Stack
;Allocate Space on Stack
;Args: A=Number of Bytes to Allocate
;Updates: STKLO, STKHI = Stack Pointer
;Updates: STKPTR = Stack Pointer
;Affects: C,N,Z
;Returns: A = Number of Bytes Allocated
; 0 if Error: Pointer Overflow or Length 0
; Y=0
STKALC: JSR STKSSP ;Save Stack Pointer
.ALLOC JSR .SAVPTR ;Save Stack Pointer
LDA TEMP0 ;If No Bytes
BEQ STKABT ; Abort Calling Routine
JSR STKADD ;Add to Stack Pointer
LDA STKEHI ;If Stack End MSB
CMP STKHI ; < Stack Pointer MSB
BCC STKRPA ; Abort Calling Routine
BNE STKALX ;Else if Not Equal
LDA STKELO ;and Stack End LSB
CMP STKLO ; < Stack Pointer LSB
BCC STKRPA ; Abort Calling Routine
STKALX: LDA TEMP0 ;Get Number of Bytes from X Register
BEQ .POPRET ; Abort Calling Routine
JSR .ADDPTR ;Add to Stack Pointer
LDA STKEND+1 ;If Stack End MSB
CMP STKPTR+1 ; < Stack Pointer MSB
BCC .ABORT ; Abort Calling Routine
BNE .ALSKIP ;Else if Not Equal
LDA STKEND ;and Stack End LSB
CMP STKPTR ; < Stack Pointer LSB
BCC .ABORT ; Abort Calling Routine
.ALSKIP LDA TEMP0 ;Get Number of Bytes from X Register
LDY #0 ;Initialize Index
STA (STKLO),Y ;Store after Allocated Area
;and fall inro STKINC
STA (STKPTR),Y ;Store after Allocated Area
;and fall into .INCPTR
;stkinc(n) - Increment Stack Pointer
;Sets: STKLO, STKHI = Stack Pointer Address
;Affects: Y,Z,N
STKINC: INC STKLO ;Increment LSB
BNE STKINX ;If Zero
INC STKHI ; Increment MSB
STKINX: RTS
;Increment Stack Pointer
.INCPTR INC STKPTR ;Increment LSB
BNE .RETURN ;If Zero
INC STKPTR+1 ; Increment MSB
RTS
;stkcmp - Compare Stack Pointer to Stack Start Address
;Uses: STKLO, STKHI = Stack Pointer Address
; STKSLO, STKSHI = Stack Start Address
;Returns: C=1,Z=1 if Stack Pointer = Stack Start
; C=1,Z=0 if Stack Pointer > Stack Start
; C=0,Z=0 if Stack Pointer < Stack Start
STKCMP: LDA STKHI ;Compare MSB
CMP STKSHI
BCC STKRTS ;If Pointer<Start Return C=0, Z=1
BNE STKRTS ;If Pointer>Start Return C=1. Z=0
LDA STKLO ;If MSB Equal
CMP STKSLO ;Compare LSB
STKRTS: RTS
;STKPTR to STKBGN
;Returns: C=1,Z=1 if STKPTR = STKBGN
; C=1,Z=0 if STKPTR > STKBGN
; C=0,Z=0 if STKPTR < STKBGN
.CMPPTR LDA STKPTR+1 ;Compare MSB
CMP STKBGN+1
BCC .RETURN ;If Pointer<Start Return C=0, Z=1
BNE .RETURN ;If Pointer>Start Return C=1. Z=0
LDA STKPTR ;If MSB Equal
CMP STKBGN ;Compare LSB
RTS
;stkdec(n) - Decrement Stack Pointer
;Sets: STKLO, STKHI = Stack Pointer Address
;.DECPTR(n) - Decrement Stack Pointer
;Sets: STKPTR = Stack Pointer Address
;Affects: X,Z,N
STKDEC: LDX STKLO ;If LSB
BNE STKDEL ; is Zero
DEC STKHI ; Decrement MSB
STKDEL: DEC STKLO ; Decrement LSB
STKDER: RTS
.DECPTR LDX STKPTR ;If LSB
BNE .DECLSB ; is Zero
DEC STKPTR+1 ; Decrement MSB
.DECLSB DEC STKPTR ; Decrement LSB
RTS
;stksiz() - Get Stack Size in Bytes
;Uses: STKLO,STKHI = Stack Pointer
;Sets: STKSLO, STKSHI = Stack Start Address
;Uses: STKPTR = Stack Pointer
;Sets: STKBGN = Stack Start Address
;Returns: A = $FF if Stack Size is Non-Zero
; $00 if Stack is Empty
; Y,X = Stack Size (MSB, LSB)
STKSIZ: LDA STKLO ;Subtract
SEC ;Start Address LSB
SBC STKSLO ;from Pointer LSB
TAX ;and Copy to X
LDA STKHI ;Subtract Start MSB
SBC STKSHI ;from Pointer MSB
TAY ;and Copy to Y
BCC STKZRO ;Return FALSE if <=0
BNE STKTRU ;Return TRUE if MSB <> 0
TXA ;Else
BEQ STKRTS ;Return FALSE if LSB = 0
STKTRU: LDA #$FF ;Else Return TRUE
RTS
STKSIZ: LDA STKPTR ;Subtract
SEC ;Start Address LSB
SBC STKBGN ;from Pointer LSB
TAX ;and Copy to X
LDA STKPTR+1 ;Subtract Start MSB
SBC STKBGN+1 ;from Pointer MSB
TAY ;and Copy to Y
BCC .RETZRO ;Return FALSE if <=0
BNE .RETTRU ;Return TRUE if MSB <> 0
TXA ;Else
BEQ .RETURN ;Return FALSE if LSB = 0
.RETTRU LDA #$FF ;Else Return TRUE
.RETURN RTS
;stkdrp(&m) - Drop Top Entry from Stack
;Note: Aborts Calling Routine if Error
;Uses: STKSLO, STKSHI = Stack Start Address
;Uses: STKBGN = Stack Start Address
;Sets: TEMP1, TEMP2 = Original Stack Pointer
;Updates: STKLO, STKHI = Stack Pointer
;Updates: STKPTR = Stack Pointer
;Affects: Y,C,N,Z
;Returns: A=Number of Bytes in Entry
; 0=Error: Stack Underflow
; Y=0
STKDRP: JSR STKSSP ;Save Stack Pointer
STKDRN: JSR STKCMP ;If Stack Pointer
BCC STKRPA ; <= Stack Start
BEQ STKRPA ; Return 0
JSR STKDEC ;Decrement Stack Pointer
STKDRP: JSR .SAVPTR ;Save Stack Pointer
.STKDRP JSR .CMPPTR ;If Stack Pointer
BCC .ABORT ; <= Stack Start
BEQ .ABORT ; Return 0
JSR .DECPTR ;Decrement Stack Pointer
LDY #0 ;Initialize Index
LDA (STKLO),Y ;Get Number of Bytes in Entry
;and fall into STKSUB
LDA (STKPTR),Y ;Get Number of Bytes in Entry
;and fall into .SUBPTR
;stksub(n) - Reduce Stack Pointer by A
STKSUB: STA TEMP0 ;Save Number in TEMP0
LDA STKLO
;Subtract A from STKPTR
.SUBPTR STA TEMP0 ;Save Number in TEMP0
LDA STKPTR
SEC ;Subtract A from LSB
SBC TEMP0
STA STKLO
LDA STKHI ;Subtract 0 from LSB
STA STKPTR
LDA STKPTR+1 ;Subtract 0 from LSB
SBC #0 ;For Borrow
STA STKHI
JSR STKCMP ;If Stack Pointer < Start
BCC STKRPA ; Restore Pointer and Return 0
STKSUE: LDA TEMP0 ;Retrieve Number of Bytes
STA STKPTR+1
JSR .CMPPTR ;If Stack Pointer < Start
BCC .ABORT ; Restore Pointer and Return 0
LDA TEMP0 ;Retrieve Number of Bytes
RTS
STKRPA: JSR STKRSP ;Restore Stack Pointer
STKABT: PLA ;Drop Return Address from Stack
.ABORT JSR .RESPTR ;Restore Stack Pointer
.POPRET PLA ;Drop Return Address from Stack
PLA ; Aborting Calling Routine
STKZRO: LDA #0 ;Set A to 0
.RETZRO LDA #0 ;Set A to 0
RTS
;stkpop(&m) - Pop Top Entry off Stack
;Args: Y,X = Address of Source Array
;Uses: STKSLO, STKSHI = Stack Start Address
;Updates: STKLO, STKHI = Stack Pointer
;Uses: STKBGN = Stack Start Address
;Updates: STKPTR = Stack Pointer
;Affects: C,N,Z
;Returns: A,Y = Number of Bytes in Entry
; 0 = Error: Stack Underflow
STKPOP: JSR SETDST ;Set Destination Address
JSR STKDRP ;Deallocate Stack Entry
STKPOS: JSR STKSRC ;Set Source Address to Stack Pointer
JSR .STKSRC ;Set Source Address to Stack Pointer
JMP MEMCPL ;Copy Bytes and Return
;stkstr(n, &m) - Push String onto Stack
;Args: Y,X = Address of Source Array
STKSTR: JSR STRLEN ;Get Length of String
BEQ .PSHSRC ;If Length > 0
BMI .PSHSRC ; and < 128
INY ; Increment Length to
TYA ; include null terminator
.PSHSRC LDY #0 ;Clear Y Index
JMP .STKPSH ;Push Bytes onto Stack
;stktop(&m) - Copy Top Entry off Stack
;Args: Y,X = Address of Source Array
;Uses: STKBGN = Stack Start Address
;Affects: C,N,Z
;Returns: A,Y = Number of Bytes in Entry
; 0 = Error: Stack Underflow
STKTOP: JSR STKPOP ;Pop Top Entry Off Stack
BEQ .RETURN ;If Underflow, Return 0
JMP .RESPTR ;Else Restore Stack Pointer and Return
;stkdup(&m) - Duplicate Top Entry on Stack
;Uses: STKBGN = Stack Start Address
; STKEND = Stack End Address
;Updates: STKPTR = Stack Pointer
;Affects: C,N,Z
;Returns: A,Y = Number of Bytes in Entry
; 0 = Error: Stack Overflow or Underflow
STKDUP: JSR STKDRP ;Deallocate Top Entry
.STKDUP JSR .STKSRC ;Set Source Pointer to Stack Pointer
JSR .RESPTR ;Restore Stack Pointer
JMP .PSHSRC ;Push Top Entry onto Stack
;stkovr(&m) - Duplicate Second Entry on Stack
;Uses: STKBGN = Stack Start Address
; STKEND = Stack End Address
;Updates: STKPTR = Stack Pointer
;Affects: C,N,Z
;Returns: A,Y = Number of Bytes in Entry
; 0 = Error: Stack Overflow or Underflow
STKOVR: JSR STKDRP ;Deallocate Top Entry
JSR .STKDRP ;Deallocate Second Entry
JMP .STKDUP ;Restore Pointer and Duplicate
;stkswp() - Swap Top Entry with Entry Below it
;Uses: STKBGN = Stack Start Address
; STKEND = Stack End Address
;Destroys: DSTPTR,TEMP0,TEMP0,TEMP1,TEMP2,TEMP3
;Affects: C,N,Z
;Returns: A,Y = Number of Bytes in Entry
; 0 = Error: Stack Overflow or Underflow
STKSWP: JSR STKOVR ;Duplicate Second Entry
BEQ .RETURN ;Exit if Error
JSR .STKDRP ;Deallocate Duplicate
STA TEMP3 ;Save Size of Duplicate
JSR .SAVPTR ;Save Pointer to Duplicate
JSR .STKDRP ;Deallocate Top Entry
JSR .STKSRC ;Set Source to Top Entry
STA DSTPTR ;Save Top Entry Size
JSR .STKDRP ;Deallocate Second Entry
LDA DSTPTR ;Retrieve Top Entry Size
JSR .COPY ;Copy Top Entry Down
JSR RESSRC ;Set Duplicate as Source
LDA TEMP3 ;Get Duplicate Length
.COPY STA TEMP0 ;Save Number of Bytes
JSR .STKDST ;Set Destination to Stack Pointer
LDY #0 ;Clear Index Register
JSR MEMCPL ;Copy Bytes and Return
STA (DSTPTR),Y ;Store Number of Bytes after Entry
SEC ;Add Number of Bytes plus 1
JSR .ADCPTR ;to Stack Pointer
TYA ;Return Number of Bytes
RTS
ENDSUBROUTINE

View File

@ -2,35 +2,20 @@
* stack - Software Stack Functions for C02 *
********************************************/
/* Add to Stack Pointer Address *
* Internal Utility Function *
* Args: b - Number of Bytes to Add */
void stkadd();
/* Set Stack Start Address *
* Args: &addr - Start Address */
void stkbgn();
/* Decrement Stack Pointer Address *
* Internal Utility Function */
void stkdec();
/* Drop Top Entry from Stack *
* Returns: A=Number of bytes dropped *
* 0 if none */
char stkdrp();
/* Set Destination to Stack Pointer *
* Returns: Y,X=Pointer Address */
void stkdst();
/* Duplicate Top Stack Entry *
* Returns: A=Number of bytes retrieved *
* 0 if none or overflow */
char stkdup();
/* Set Stack End Address *
* Args: &addr - End Address */
void stkend();
/* Increment Stack Pointer Address *
* Internal Utility Function */
void stkinc();
/* Duplicate Entry Under Top of Stack *
* Returns: A=Number of bytes retrieved *
* 0 if none or overflow */
char stkovr();
/* Pop Top Stack Entry into Array *
* Args: n - Number of bytes to write *
@ -46,34 +31,30 @@ char stkpop();
* $00 if block was overflowed */
char stkpsh();
/* Get Stack Pointer Address *
* Returns: Y,X=Pointer Address */
void stkptr();
/* Restore Stack Pointer Address *
* Internal Utility Function */
void stkrsp();
/* Reset Stack Pointer to Stack Start *
* Returns: Y,X=Pointer Address */
void stkrst();
/* Set Stack Pointer Address *
* Internal Utility Function *
* Args: &addr - Pointer Address */
void stkset();
/* Save Stack Pointer Address *
* Internal Utility Function */
void stkssp();
/* Get Stack Size *
* Returns: A=$FF if size greater than 0 *
* $00 if stack is empty *
* Y,X=Stack size in bytes */
void stksiz();
/* Subtract from Stack Pointer Address *
* Internal Utility Function *
* Args: b - Number of Bytes to Subtract */
void stksub();
/* Push String onto Stack *
* Args: &m - String to push *
* Returns: A=$FF if bytes were written *
* $00 if block was overflowed */
char stkstr();
/* Swap Top and Second Stack Entries *
* Returns: A=Number of bytes in new top *
* 0 if none or overflow */
char stkswp();
/* Copy Top Stack Entry into Array *
* Args: n - Number of bytes to write *
* &m - Array to pop contents into *
* Returns: A=Number of bytes retrieved *
* 0 if none */
char stktop();

View File

@ -1,80 +0,0 @@
;C02 stack module assembly language subroutines
;Requires external zero page variables
;STKLO, STKHI, DSTLO, DSTHI, SRCLO, SRCHI
;external variables
;STKSLO, STKSHI, STKELO, STKEHI, TEMP0, TEMP1, TEMP2, TEMP3
;external routines
;MEMCPL, STKADD, STKDRN, STKPSA, STKRSP, STKSRC, STKSSP, STRLEN
;stkstr(n, &m) - Push String onto Stack
;Args: Y,X = Address of Source Array
STKSTR: JSR STRLEN ;Get Length of String
BEQ STKSTY ;If Length > 0
BMI STKSTY ; and < 128
INY ; Increment Length to
TYA ; include null terminator
STKSTY: LDY #0 ;Clear Y Index
JMP STKPSA ;Push Bytes onto Stack
;stktop(&m) - Copy Top Entry off Stack
;Args: Y,X = Address of Source Array
;Uses: STKSLO, STKSHI = Stack Start Address
;Affects: C,N,Z
;Returns: A,Y = Number of Bytes in Entry
; 0 = Error: Stack Underflow
STKTOP: JSR STKPOP ;Pop Top Entry Off Stack
BEQ STKSWR ;If Underflow, Return 0
JMP STKRSP ;Else Restore Stack Pointer and Return
;stkdup(&m) - Duplicate Top Entry on Stack
;Uses: STKSLO, STKSHI = Stack Start Address
; STKELO, STKEHI = Stack End Address
;Updates: STKLO, STKHI = Stack Pointer
;Affects: C,N,Z
;Returns: A,Y = Number of Bytes in Entry
; 0 = Error: Stack Overflow or Underflow
STKDUP: JSR STKDRP ;Deallocate Top Entry
STKDUS: JSR STKSRC ;Set Source Pointer to Stack Pointer
JSR STKRSP ;Restore Stack Pointer
JMP STKSTY ;Push Top Entry onto Stack
;stkovr(&m) - Duplicate Second Entry on Stack
;Uses: STKSLO, STKSHI = Stack Start Address
; STKELO, STKEHI = Stack End Address
;Updates: STKLO, STKHI = Stack Pointer
;Affects: C,N,Z
;Returns: A,Y = Number of Bytes in Entry
; 0 = Error: Stack Overflow or Underflow
STKOVR: JSR STKDRP ;Deallocate Top Entry
JSR STKDRN ;Deallocate Second Entry
JMP STKDUS ;Restore Pointer and Duplicate
;stkswp() - Swap Top Entry with Entry Below it
;Uses: STKSLO, STKSHI = Stack Start Address
; STKELO, STKEHI = Stack End Address
;Destroys: DSTLO,TEMP0,TEMP0,TEMP1,TEMP2,TEMP3
;Affects: C,N,Z
;Returns: A,Y = Number of Bytes in Entry
; 0 = Error: Stack Overflow or Underflow
STKSWP: JSR STKOVR ;Duplicate Second Entry
BEQ STKSWR ;Exit if Error
JSR STKDRN ;Deallocate Duplicate
STA TEMP3 ;Save Size of Duplicate
JSR STKSSP ;Save Pointer to Duplicate
JSR STKDRN ;Deallocate Top Entry
JSR STKSRC ;Set Source to Top Entry
STA DSTLO ;Save Top Entry Size
JSR STKDRN ;Deallocate Second Entry
LDA DSTLO ;Retrieve Top Entry Size
JSR STKSWC ;Copy Top Entry Down
JSR RESSRC ;Set Duplicate as Source
LDA TEMP3 ;Get Duplicate Length
STKSWC: STA TEMP0 ;Save Number of Bytes
JSR STKDST ;Set Destination to Stack Pointer
LDY #0 ;Clear Index Register
JSR MEMCPL ;Copy Bytes and Return
STA (DSTLO),Y ;Store Number of Bytes after Entry
SEC ;Add Number of Bytes plus 1
JSR STKADC ;to Stack Pointer
TYA ;Return Number of Bytes
STKSWR: RTS

View File

@ -1,31 +0,0 @@
/*********************************************
* stackx - Extended Stack Functions for C02 *
*********************************************/
/* Duplicate Top Stack Entry *
* Returns: A=Number of bytes retrieved *
* 0 if none or overflow */
char stkdup();
/* Duplicate Entry Under Top of Stack *
* Returns: A=Number of bytes retrieved *
* 0 if none or overflow */
char stkovr();
/* Push String onto Stack *
* Args: &m - String to push *
* Returns: A=$FF if bytes were written *
* $00 if block was overflowed */
char stkstr();
/* Swap Top and Second Stack Entries *
* Returns: A=Number of bytes in new top *
* 0 if none or overflow */
char stkswp();
/* Copy Top Stack Entry into Array *
* Args: n - Number of bytes to write *
* &m - Array to pop contents into *
* Returns: A=Number of bytes retrieved *
* 0 if none */
char stktop();

View File

@ -1,207 +1,132 @@
/***********************************************
* TESTSTK - Test Stack Manipulation Functions *
* STKTEST - Test Stack Manipulation Functions *
* Assumes free RAM from $7FFF to $807E *
***********************************************/
//use -h option on command line when compiling
#include <stddef.h02>
#include <stdlib.h02>
#include <intlib.h02>
#include <stdio.h02>
#include <stdiox.h02>
#include <string.h02>
#include <memory.h02>
#include <stack.h02>
char c,f,g,i;
char aa,xx,yy;
char zz,lo,hi;
char c,f,g,i,n;
char aa,xx,yy,zz;
int addr,adr,cptr,csiz,nn,optr,ptr,siz,yx;
const char r={6,7,8,9};
const char s="Test String";
const char s="TEST STRING";
char t[255];
char stackb[128], stacke;
void pass() {putln(" PASS");}
void fail() {putln(" FAIL"); goto exit;}
void psorfl(aa) {if (aa) pass(); else fail();}
void florps(aa) {if (aa) fail(); else pass();}
void equals(aa,zz) {A = (aa == zz) ? #TRUE : #FALSE;}
void prtadr(adr) {puts("$"); putwrd(adr);}
void prtstk() {aa,yy,xx=stksiz(); for (zz=0; zz<xx; zz++) {if (zz) putc(','); putdec(stackb[zz]);}}
void errstk() {newlin(); puts("STACK={"); prtstk(); putc(')'); fail();}
void addsub(zz,yx) {if (zz:-) subayx(-zz+1,yx); else addayx(zz+1,yx);}
void updptr(aa) {if (aa) cptr=addsub(aa,cptr); else cptr=stkptr;}
void updsiz(aa) {if (aa) csiz=addsub(aa,csiz); else csiz=0;}
void cmpadr(adr) {f = equals(<addr,<adr); g = equals(>addr,>adr); return f & g;}
void chkadr(yx) {prtadr(addr); psorfl(cmpadr(yx));}
void chkint(yx) {putint(addr); psorfl(cmpadr(yx));}
void chkmem(aa,yx) {setdst(optr); florps(memcmp(aa, yx));}
void chkmet(aa,yx) {setdst(t); florps(memcmp(aa, yx));}
void chkptr(aa,ptr) {addr=stkptr; puts(" STKPTR="); chkadr(ptr); optr=stkptr;}
void chkres(aa,zz) {printf(zz,"=%d");if (aa<>zz) fail();}
void chksiz(siz) {puts(" STKSIZ()="); addr=stksiz(); chkint(siz);}
void chkstr(yx) {setdst(optr); florps(strcmp(yx));}
void chkstt(yx) {setdst(t); florps(strcmp(yx));}
void pause() {if (anykey()==#ESCKEY) goto exit;}
main:
for (i=0;i<$20;i++) srclo[i]=0; //Initialize Pointers
stkbgn = &stackb; puts("STKBGN="); prtadr(stkbgn); newlin();
stkend = &stacke; puts("STKEND="); prtadr(stkend); newlin();
puts("Setting Stack Start Address\t");
puts("stkbgn($7FFF)\t");
stkbgn(&$7FFF); lo=stkslo; hi=stkshi;
setdst("stks"); cklohi(&$7FFF);
putln("STKRST()");
stkrst();
updptr(0); chkptr(stkbgn); updsiz(0); chksiz(csiz);
puts("Setting Stack End Address\t");
puts("stkend($807E)\t");
stkend(&$807E); lo=stkelo; hi=stkehi;
setdst("stke"); cklohi(&$807E);
//Push Array - Stack=R
puts("STKPSH(@R,R)");
n=stkpsh(@r,r); chkres(@r,n); chkmem(@r, &r);
updptr(n); chkptr(cptr); updsiz(n); chksiz(csiz);
puts("Setting Stack Pointer Address\t");
puts("stkset($7765)\t");
stkset(&$7765); lo=stklo; hi=stkhi;
setdst("stk"); cklohi(0,&$7765);
chksiz(#FALSE, &$F766);
//Duplicate Top - Stack=R,R
puts("STKDUP()");
n=stkdup(); chkres(@r,n); chkmem(@r, &r);
updptr(n); chkptr(cptr); updsiz(n); chksiz(csiz);
puts("Resetting Stack Pointer\t\t");
puts("stkrst()\t");
stkrst(); lo=stklo; hi=stkhi;
setdst("stk"); cklohi(0,&$7FFF);
chksiz(#FALSE, &0);
//Push String - Stack=S,R,R
puts("STKSTR(S)");
n=stkstr(s); chkres(@s+1,n); chkstr(s);
updptr(n); chkptr(cptr); updsiz(n); chksiz(csiz);
puts("Getting Stack Pointer Address\t");
puts("stkptr()\t");
aa, hi, lo = stkptr();
setdst(""); cklohi(0,&$7FFF);
pause();
puts("Setting Source to Stack Pointer\t");
puts("stksrc()\t");
stksrc(); lo=srclo; hi=srchi;
setdst("src"); cklohi(0,&$7FFF);
//Copy Second to Top - Stack=R,S,R,R
puts("STKOVR()");
n=stkovr(); chkres(@r,n); chkmem(@r, &r);
updptr(n); chkptr(cptr); updsiz(n); chksiz(csiz);
puts("Setting Dest. to Stack Pointer\t");
puts("stkdst()\t");
stkdst(); lo=dstlo; hi=dsthi;
setdst("src"); cklohi(0,&$7FFF);
//Swap Top and Second - Stack=S,R,R,R
puts("STKSWP()");
n=stkswp(s); chkres(@s+1,n); chkstr(s);
chkptr(cptr); chksiz(csiz);
puts("Incrementing Stack Pointer\t");
puts("stkinc()\t");
stkinc(); lo=stklo; hi=stkhi;
setdst("stk"); cklohi(0,&$8000);
chksiz(#TRUE, &1);
//Read String - Stack=S,R,R,R
puts("STKTOP(T)");
n=stktop(t); chkres(@s+1,n); chkstt(s);
chkptr(cptr); chksiz(csiz);
puts("Decrementing Stack Pointer\t");
puts("stkdec()\t");
stkdec(); lo=stklo; hi=stkhi;
setdst("stk"); cklohi(0,&$7FFF);
chksiz(#FALSE, &0);
//Pop String - Stack=R,R,R
puts("STKPOP(T)");
n=stkpop(&t); chkres(@s+1,n); chkstt(s);
updptr(-n); chkptr(cptr); updsiz(-n); chksiz(csiz);
c = anykey(); if (c == #esckey) goto exit;
pause();
puts("Pushing Array onto Stack\t");
puts("stkpsh(@r,$r)\t");
aa,hi,lo=stkptr(); //Save Stack Pointer
f=stkpsh(@r,&r); printf(f,"bytes=%d:");
setdst(?,hi,lo); g=(memcmp(@r, &r)==0) ? #TRUE : #FALSE;
psorfl(f & g); chksiz(#TRUE, &5); chkptr(&$8004);
//Drop Copy - Stack=R,R
puts("STKDRP()");
n=stkdrp(); chkres(@r,n); pass();
updptr(-n); chkptr(cptr); updsiz(-n); chksiz(csiz);
puts("Duplicating Top of Stack\t");
puts("stkdup()\t");
aa,hi,lo=stkptr(); //Save Stack Pointer
f=stkdup(); printf(f,"bytes=%d:");
setdst(?,hi,lo); g=(memcmp(@r, &r)==0) ? #TRUE : #FALSE;
psorfl(f & g); chksiz(#TRUE, &10); chkptr(&$8009);
//Drop Duplicate - Stack=R
puts("STKDRP()");
n=stkdrp(); chkres(@r,n); pass();
updptr(-n); chkptr(cptr); updsiz(-n); chksiz(csiz);
puts("Pushing String onto Stack\t");
puts("stkstr(&s)\t");
aa,hi,lo=stkptr(); //Save Stack Pointer
f=stkstr(&s); printf(f,"bytes=%d:");
setdst(?,hi,lo); g=(strcmp(&s)==0) ? #TRUE : #FALSE;
psorfl(f & g); chksiz(#TRUE, &23); chkptr(&$8016);
//Pop Array - Stack Empty
puts("STKPOP(&T)");
n=stkpop(&t); chkres(@r,n); chkmet(@r,t);
updptr(-n); chkptr(cptr); updsiz(-n); chksiz(csiz);
puts("Duplicating Second Stack Entry\t");
puts("stkovr()\t");
aa,hi,lo=stkptr(); //Save Stack Pointer
f=stkovr(); printf(f,"bytes=%d:");
setdst(?,hi,lo); g=(memcmp(@r, &r)==0) ? #TRUE : #FALSE;
psorfl(f & g); chksiz(#TRUE, &28); chkptr(&$801B);
pause();
c = anykey(); if (c == #esckey) goto exit;
//Pop from Empty Stack
puts("STKPOP(&T)");
n=stkpop(&t); chkres(0,n); pass();
chkptr(cptr); chksiz(csiz);
puts("Dropping Duplicate off Stack\t");
puts("stkdrp()\t");
f=stkdrp(); printf(f,"bytes=%d:");
g=(f==4) ? #TRUE : #FALSE;
psorfl(f & g); chksiz(#TRUE, &23); chkptr(&$8016);
//Overflow Stack - Stack Empty
puts("STKPSH(255,&T)");
n=stkpsh(255,&t); chkres(0,n); pass();
chkptr(cptr); chksiz(csiz);
puts("Copying String from Stack\t");
puts("stktop(&t)\t");
f=stktop(&t); setdst(&t); printf("\"%s\":");
g=(strcmp(&s)==0) ? #TRUE : #FALSE;
psorfl(f & g);
chkptr(&$8016);
puts("Popping String off Stack\t");
puts("stkpop(&t)\t");
f=stkpop(&t); setdst(&t); printf("\"%s\":");
g=(strcmp(&s)==0) ? #TRUE : #FALSE;
psorfl(f & g);
chkptr(&$8009);
puts("Dropping Duplicate off Stack\t");
puts("stkdrp()\t");
f=stkdrp(); printf(f,"bytes=%d:");
g=(f==4) ? #TRUE : #FALSE;
psorfl(f & g);
chkptr(&$8004);
puts("Popping Array off Stack\t\t");
puts("stkpop(&t)\t");
f=stkpop(&t); prtary(f); puts(": ");
g=(memcmp(f,&r)==0) ? #TRUE : #FALSE;
psorfl(f & g);
chkptr(&$7FFF);
puts("Popping off Empty Stack\t\t");
puts("stkpop(&t)\t");
f=stkpop(&t); printf(f,"bytes=%d:");
if (f) fail(); else pass();
chkptr(&$7FFF);
puts("Overflowing Stack\t\t");
puts("stkpsh(255,&t)\t");
f=stkpsh(255,&t); printf(f,"bytes=%d:");
if (f) fail(); else pass();
chkptr(&$7FFF);
putln("Tests Complete");
putln("TESTS COMPLETE");
goto exit;
void chkptr(aa,yy,xx) {
puts("\tChecking Stack Pointer\t\t\t");
puts("address=$"); prbyte(stkhi); prbyte(stklo); putc(':');
xx = (stklo == xx) ? #TRUE : #FALSE;
yy = (stkhi == yy) ? #TRUE : #FALSE;
psorfl(xx & yy);
}
void prtary(aa) {
putc('{');
for (i=0;i<aa;i++) {
if (i) putc(',');
putdec(t[i]);
}
putc('}');
}
void cklohi(aa,yy,xx) {
putdst(); puts("lo=$"); prbyte(lo); putc(' ');
putdst(); puts("hi=$"); prbyte(hi); putc(':');
xx = (lo == xx) ? #TRUE : #FALSE;
yy = (hi == yy) ? #TRUE : #FALSE;
psorfl(xx & yy);
}
void chksiz(aa,yy,xx) {
puts("\tChecking Stack Size\t");
puts("stksiz()\t");
zz, dsthi, dstlo = stksiz();
printf(zz, "Sts=$%x Size=$%w:");
if (zz == aa and dsthi == yy and dstlo == xx ) pass();
else {fail(); goto exit;}
}
void psorfl(aa) {if (aa) pass(); else {fail(); goto exit;}}
void pass() {putln(" Pass");}
void fail() {putln(" Fail");}
puts("Swapping Top and Second Entry\t");
puts("stkswp()\t");
f=stkswp(); printf(f,"bytes=%d:");
g=(f==12) ? #TRUE : #FALSE;
psorfl(f & g);
chkptr(&$801B);
puts("Dropping Swapped Entry off Stack\t");
puts("stkdrp()\t");
puts("Dropping Swapped Entry off Stack");
puts("stkdrp()");
f=stkdrp(); printf(f,"bytes=%d:");
g=(f==4) ? #TRUE : #FALSE;
psorfl(f & g);