From 414d673db5fbdddc1025faeed2ddf8f411b49f12 Mon Sep 17 00:00:00 2001 From: Curtis F Kaylor Date: Mon, 19 Oct 2020 22:44:24 -0400 Subject: [PATCH] Combined stack and stackx modules, updated documentation and test program --- doc/stack.txt | 235 ++++++++++++++++------------- include/stack.a02 | 360 +++++++++++++++++++++++++-------------------- include/stack.h02 | 69 ++++----- include/stackx.a02 | 80 ---------- include/stackx.h02 | 31 ---- test/stktest.c02 | 255 ++++++++++++-------------------- 6 files changed, 449 insertions(+), 581 deletions(-) delete mode 100644 include/stackx.a02 delete mode 100644 include/stackx.h02 diff --git a/doc/stack.txt b/doc/stack.txt index 992ab14..951434c 100644 --- a/doc/stack.txt +++ b/doc/stack.txt @@ -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 #include + #include #include +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 diff --git a/include/stack.a02 b/include/stack.a02 index 0e1ca46..0aec41a 100644 --- a/include/stack.a02 +++ b/include/stack.a02 @@ -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 PointerStart 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 PointerStart 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 \ No newline at end of file diff --git a/include/stack.h02 b/include/stack.h02 index a80f9db..d957282 100644 --- a/include/stack.h02 +++ b/include/stack.h02 @@ -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(); diff --git a/include/stackx.a02 b/include/stackx.a02 deleted file mode 100644 index e7cc6ed..0000000 --- a/include/stackx.a02 +++ /dev/null @@ -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 diff --git a/include/stackx.h02 b/include/stackx.h02 deleted file mode 100644 index 42f4510..0000000 --- a/include/stackx.h02 +++ /dev/null @@ -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(); diff --git a/test/stktest.c02 b/test/stktest.c02 index 6fd74c4..944fa94 100644 --- a/test/stktest.c02 +++ b/test/stktest.c02 @@ -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 #include +#include #include #include #include #include #include -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; zzaddr,>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