6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sun Nov 24, 2024 8:35 pm

All times are UTC




Post new topic Reply to topic  [ 11 posts ] 
Author Message
PostPosted: Thu Aug 18, 2016 10:13 am 
Offline

Joined: Sat Jul 09, 2016 6:01 pm
Posts: 180
http://codebase64.org/doku.php?id=base:quicksort_16-bit_elements
http://codebase64.org/doku.php?id=base:shell_sort_16-bit_elements
They are the fastest general purpose sort routines for 6502. :)

_________________
my blog about processors


Top
 Profile  
Reply with quote  
PostPosted: Thu Aug 18, 2016 3:04 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8514
Location: Midwestern USA
litwr wrote:

From your write-up:

    It is well known that the best, the fastest sort routine is Quicksort. It is very odd that it is not implemented for 6502 for all of 42 years, from 1975 to 2016.

A quicksort assembly language program for the Commodore 64 was published c. 1984. The implementation sorted string variables contained in an array and could manage a full sort on one thousand elements in about a second. I just can't remember where I saw it, but I did adapt it to a mailing list program I wrote that ran on the C-64.

A quirk of the quicksort is that if run on an array that is mostly, but not completely, sorted, the run time will be greater than it would be on the same array if completely unsorted.

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
PostPosted: Thu Aug 18, 2016 3:12 pm 
Offline
User avatar

Joined: Sun Jun 30, 2013 10:26 pm
Posts: 1952
Location: Sacramento, CA, USA
http://lmgtfy.com/?q=6502+quicksort

;)

Mike B.


Top
 Profile  
Reply with quote  
PostPosted: Fri Aug 19, 2016 7:53 am 
Offline

Joined: Sat Jul 09, 2016 6:01 pm
Posts: 180
BigDumbDinosaur wrote:
A quicksort assembly language program for the Commodore 64 was published c. 1984. The implementation sorted string variables contained in an array and could manage a full sort on one thousand elements in about a second. I just can't remember where I saw it, but I did adapt it to a mailing list program I wrote that ran on the C-64.
A quirk of the quicksort is that if run on an array that is mostly, but not completely, sorted, the run time will be greater than it would be on the same array if completely unsorted.

Thanks. I rewrote the phrase and added a link to another 6502 Quicksort implementation (BTW it is very limited). The mentioned C64 program is not available. :(
Quicksort at Codebase64 is very fast for fully or partially sorted data. It is possible to create artificial filling (it will look like random) which may slow down the sort but the probability of a case that such filling is appeared naturally is almost impossible.

_________________
my blog about processors


Top
 Profile  
Reply with quote  
PostPosted: Tue Dec 06, 2016 2:41 pm 
Offline

Joined: Tue Jun 08, 2004 11:51 pm
Posts: 213
Hi
Although, QuickSort is the fastest general purpose sort it is
rarely the best sort for all data sets.
It has even poorer speed when the data needs to be sorted for
non-ascii order.
QuickSort is an nlogn sort. This means that simpler sorts such as
a modulo n basket sort can be many times faster for large data
sets and simple sort keys.
Another powerful sort is a distribution sort.
I participated in a sort contest once where there were many types of sorts.
The contest was to sort 1k 16 bit integers. Most of the contestants
had sort running at about .5 to 10 seconds on x386 level machines.
My sort ran so fast that it had to be looped 10 times to use the
PC's time counter. Without that it often reported 0 time.
I once had a friend that was sorting a large number of names for
the boyscouts mailing list. I wrote a self truncating distribution
sort for him that he was quite pleased with.
Both the basket sort and the distribution sort can do out of order
sorts with almost zero time penalty.
QuickSort was written when sorting had to be done in place on small
memories. When you have enough space for 2 copies of the data,
the distribution sorts are really fast. If you have enough for 2 plus
pointers a basket sort can do really well.
Even if you don't have a lot of space doing a presort with a fast
sort, followed by a merge sort can still beat most QuickSort on
large data sets.
Dwight


Top
 Profile  
Reply with quote  
PostPosted: Wed Dec 07, 2016 4:55 am 
Offline

Joined: Tue Jun 08, 2004 11:51 pm
Posts: 213
If anyone wants to code this up on a larger machine, I can describe it.
I have a tiny KIM-1 so I'll not be sorting 1K words of data with it.
Maybe someone with a C-64 or something. It is actually quite simple.
Dwight


Top
 Profile  
Reply with quote  
PostPosted: Wed Dec 07, 2016 5:40 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8546
Location: Southern California
Could you write it up so we can post it at http://6502.org/source/#sorting ?

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
PostPosted: Wed Dec 07, 2016 7:42 pm 
Offline

Joined: Tue Jun 08, 2004 11:51 pm
Posts: 213
GARTHWILSON wrote:
Could you write it up so we can post it at http://6502.org/source/#sorting ?


Hi Garth
I'm just not good enough to write 6502 code without debugging it. To add to that, I use my own
home made assembler. I don't think others would find it useful.
I can describe it here and anyone could code it up.

Bunch deleted!!
Please see later post with code!
Dwight


Last edited by dwight on Sat Dec 10, 2016 9:07 pm, edited 1 time in total.

Top
 Profile  
Reply with quote  
PostPosted: Fri Dec 09, 2016 5:55 am 
Offline

Joined: Tue Jun 08, 2004 11:51 pm
Posts: 213
I've been trying to code it up and found an error in the Sign sorting.
My code it not yest read but will be soon.
Dwight


Top
 Profile  
Reply with quote  
PostPosted: Sat Dec 10, 2016 7:12 pm 
Offline

Joined: Tue Jun 08, 2004 11:51 pm
Posts: 213
Found another error on assigning space for TEMPX. Dec 13, 4:08 PST

I found an error. I forgot a loop I've fixed it.

OK. Here is the text ( corrected ) and some code I wrote. I believe it
to be bug free but one never knows with software.
If you find a bug, let me know, please?

Radix 256 Distribution Sort
allocate some page zero pointers
and temportrary TEMP of 2 bytes

Arrays needed for the data to be sorted:
allocate in RAM
Data 1Kx2 The data starts and ends here
Buff 1Kx2 This is used to hold the intermediate sort
MSBCntrPntr 256x2 bytes These locatins will be used for both
LSBCntrPntr 256x2 bytes counter and then pointers to outputs.

Set MSBCntrPntr and LSBCntrPntr to all zeros

Make one pass through the data and update counters both LSBCntrPntr
and MSBCntrPntr.

Scan each word in the DATA array. Using the LSB and the MSB
as indexes into the LSBCntrPntr and MSBCntrPntr arrays
( note these are 16 bit locations )
increment the value at that location.

Doing this for eash value from the DATA array you will now have
counter of each value of bytes in the two CntrPntr arrays.
As an example the number of LSBs that were $55 would be in the
LSBCntrPntr($55).

Now we know the distribution of the parts to sort ( hense the name ).

We will now convert the counts to address to point into the arrays
BUFF and DATA.

For each value in the LSBCntrPntr array starting at LSBCntrPntr(0),
take the count out and save it to TEMP.
Replace it with the BUFF address.
Add the value from TEMP to the address of BUFF.
For all the rest of the locations replace the value there with the
running total of counts and the address of BUFF

Repeat this for MSBCntrPntr using DATA as the first address but
start at LSBCntrPntr($80) and rap around from LSBCntrPntr($FF)
to LSBCntrPntr($00) and complete the array.

As am example: If LSBCntrPntr(0)=3, LSBCntrPntr(1)=2, LSBCntrPntr(2)=6
and the address of BUFF were $4000, the locations would be
LSBCntrPntr(0)=$4000
LSBCntrPntr(1)=$4003
LSBCntrPntr(2)=$4005
and the next total is $400B for the next cell.

We now are ready to do an insertion of the data.
Start by moving things from the DATA to the BUFF based on
the LSB of the DATA value as an index into LSBCntrPntr().
Each time you use that pointer in LSBCntrPntr(), increment
that pointer in LSBCntrPntr().

When all the values have been moved from DATA to BUFF,
repeat, the similar steps of moving by using MSBCntrPntr()
in the same way.

That is it. DATA has been sorted!
QuickSort is a knLogn while this sort is kn+c type sort.
That means that for some size of data this distribution sort
will beat QuictSort. My experience is that for sorting integers,
someplace between 30 and 100, QuickSort falls behind. The Logn
starts to dominate. For the distribution sort, the +c overhead
is constant and even though K is large, Logn, of QuickSort, catches up
and overtakes the +c.
Dwight

Code:
         
     ; I have macros to deal with short branches so I don't have
     ; a lot of meaninless labels.
     ; 'BEGIN' is a marker, useally useless label
     ; 'UNTIL ZERO' is the same as BNE
     ; 'IF CARRY' is the same as BNC
     ; 'ENDIF' The place the IF skips to
     ;
     ; My array pointers are split so that accessing the low and high part
     ; doesn't take any fiddling. The data is all normal 16 bits in two
     ; consecutive bytes. My pointers are the same offset in the two
     ; arrays so Y is always the same. It is a little confusing but I like it.
     ; There are several places where the code could be optimized but
     ; this gives one the general idea and is still quite fast.
     ; I've written this code without a machine to test it on but have
     ; made several passes through and believe it is mostly bugless.
   
     ; These arrays should all be assigned on $100 boundaries!!!!!     
     DATA EQU $1000  ; 1k words of unsorted data input and sorted output     
     BUFF EQU $1800  ; 1k words for intermediate storage     
     DSIZE EQU $400  ; words   
                ; counter arrays are split for convenience     
     LCPLoc  EQU $2000  ; LSBs counter and pointer     
     LCPLocH  EQU $2100  ; LSBs counter and pointer high     
     MCPLoc  EQU $2200  ; MSBs counter and pointer     
     MCPLocH  EQU $2300  ; MSBs counter and pointer high     
     CNTZ EQU #100   ; number of words in pointers     
         
; ZERO PAGE ASSIGNMENTS
     $20 EQU FROMPNTR     ;  fetch pointer     
     $22 EQU TOPNTR       ;  to pointer for moves     
     $24 EQU LPNTR      ;   pointer to LSB counter and output pointers     
     $26 EQU LPNTRH     
     $28 EQU MPNTR      ;   pointer to MSB counter and output pointers     
     $2A EQU MPNTRH     
     $2C EQU PNTRL      ;     General purpose     
     $2E EQU PNTRH      ;     General purpose         
     $30 EQU TEMPY     
     $31 EQU TEMP ; 16 BIT IF NEEDED     
     $33 EQU TOTAL ; 16 BIT
     $35 EQU TEMPX
      ; next available $36   
         
         ORG $4000     
     DISP_SORT     
     INITS     
         
             LDX # 0     ; assumes $100 aligned and consecutive     
             STX PNTR     
             LDX # LCPLocL/$100     
             STX PNTR+1     
             JSR ZEROS100     
             JSR ZEROS100     
             JSR ZEROS100     
             JSR ZEROS100     
         
     DOCNTS  LDX # 0   ; setup from DATA as input values     
             STX FROMPNTR     
             LDY # DATA/$100     
             STY FROMPNTR+1     

             STX LPNTR
             LDY # LCPLocH
             STY LPNTRH

             STX MPNTR
             LDY # MCPLocH
             STY MPNTRH

             LDX DSIZE*2/$100 ; How many $80 16 bit value loops to do
             CLC     
               LDY $0  ; is the to index
               STY TEMPY
             BEGIN    ;  needs 8 loop to do $400 words or $800
               BEGIN   ; Over $100 but only $80 words
                 CLC     
                 LDY TEMPY        ; Y is even for LSBs
 
                 LDA (FROMPNTR),Y ; first LSBs value   
                 TAY

                 LDA # 1     
                 ADC (LPNTR),Y     
                 STA (LPNTR),Y     
                 IF CARRY     
                   LDA # 0     
                   ADC (LPNTRH),Y ; notice how these arrays are split. It reduces the amount of Y fiddling
                   STA (LPNTRH),Y ;  at no extra cost in space   
                 ENDIF     
         
                 INC TEMPY
                 LDY TEMPY        ; Y is odd  for MSBs

                 LDA (FROMPNTR),Y ; now MSB     
                 TAY

                 LDA # 1     
                 ADC (MPNTR),Y     
                 STA (MPNTR),Y     
                 IF CARRY     
                   LDA # 0     
                   ADC (MPNTRH),Y
                   STA (MPNTRH),Y   
                 ENDIF     
         
                 INC TEMPY  ; Y is even   
               UNTIL ZER0     
         
               ; ONLY DID 1/4 of DATA for each loop     
                INC FROMPNTR+1     
         
               DEX     
             UNTIL ZERO      ; do the rest
         
         
     ; COUNTS ARE DONE     
     ; now change the counters to pointers     
         
     CONVRT2PNTRS
             ; LSB counters to pointers
             LDX # 0   
             STX PNTRL     
             LDY # LCPLoc/$100     
             STY PNTRL+1     

             STX PNTRH     
             LDY # LCPLocH/$100     
             STY PNTRH+1     

             STX TOTAL     
             LDY # BUFF/$100     
             STY TOTAL+1     

             LDY # 0  ; no sign offset for LSBs     
             JSR MKPNTR
     
             ; Now MSB counter to pointers         
             LDX # 0
             STX PNTRL     
             LDY # MCPLoc/$100     
             STY PNTRL+1     

             STX PNTRH     
             LDY # MCPLocH/$100     
             STY PNTRH+1     

             STX TOTAL     
             LDY # DATA/$100     
             STY TOTAL+1     

             LDY # $80  ; does signed by starting at the center   
             JSR MKPNTR     
         
     ; Now LCPLoc and MCPLoc have the pointers to move data. 
   
             LDX # 0     
             STX PNTRL     
             LDY # LCPLoc/$100     
             STY PNTRL+1     

             STX PNTRH     
             LDY # LCPLocH/$100     
             STY PNTRH+1     

             STX FROMPNTR     
             LDY # DATA/$100     
             STY FROMPNTR+1

             STX TOPNTR
             LDY # BUFF/$100
             STY TOPNTR+1   

             LDY # 0         ; DATA OFFSET FOR MSB AND LSB     
             JSR MOVEIT     
         
             LDX # 0     
             STX PNTRL     
             LDY # MCPLoc/$100     
             STY PNTRL+1     

             STX PNTRH     
             LDY # MCPLocH/$100     
             STY PNTRH+1     

             STX FROMPNTR     
             LDY # BUFF/$100     
             STY FROMPNTR+1

             STX TOPNTR
             LDY # DATA/$100
             STY TOPNTR     

             LDY # 1  ; DATA OFFSET FOR MSB AND LSB     
             JSR MOVEIT     
                   
     DONE    JMP DONE ; replace with RTS if called from someplace            
           


     ; subroutines     
                 
     MOVEIT     ; used to move items from DATA to BUFF and back
          LDX # DSIZE*2/$100     
          BEGIN  ; 8 times   
            ; FETCH POINTER AND PUT IN TOPNTR     
            ; INCREMENT THE POINTER BY 2     
            ; MOVE THE @ FROMPNTR TO @ TOPNTR
            STX TEMPX
            LDX # $80
            BEGIN ; $80 times over $100 address
              STY TEMPY
              LDA (FROMPNTR),Y   ; Y is 0 or 1 depending on LSB or MSB pointers 
              TAY     
              LDA (PNTRL),Y     
              STA TOPNTR     
              LDA (PNTRH),Y     
              STA TOPNTR+1     
              ; INCREMENT THAT POINTER LOCATION BY 2     
              CLC     
              LDA (PNTRL),Y     
              ADC # 2   ;  ALWAYS EVEN SO ONLY SECOND ADD MAKES CARRY
              STA (PNTRL),Y     
              IF CARRY     
                LDA (PNTRH),Y     
                ADC # 0     
                STA (PNTRH),Y     
              ENDIF     
              ; MOVE THE @ FROMPNTR TO @ TOPNTR     
              LDY # 0     
              LDA (FROMPNTR),Y     
              STA (TOPNTR),Y     
              INY
              LDA (FROMPNTR),Y
              STA (TOPNTR),Y     
              LDA FROMPNTR
              ADC # 2         
              IF CARRY     
                INC FROMPNTR+1     
              THEN
              LDY TEMPY
              INX
            UNTIL ZERO
            LDX TEMPX     
            DEX     
          UNTIL ZERO     
          RTS     
         
     MKPNTR   ; X IS NUMBER TO DO    Y IS FIRST ADDRESS, 0 OR $80
          CLC     
          BEGIN     ; $100 times
            LDA (PNTRH),Y     
            STA TEMP+1     
            LDA TOTAL+1     
            STA (PNTRH),Y     
            LDA (PNTRL),Y     
            STA TEMP            
            LDA TOTAL     
            STA (PNTRL),Y
     
            ADC TEMP  ; 2 TIMES VALUE IS ALWAYS EVEN
            ADC TEMP  ; CAN ONLY CREATE CARRY ON SECOND ADD 
            STA TOTAL
                 
            LDA TOTAL+1     
            ADC TEMP+1  ; never carries as max address is less than 64K
            ADC TEMP+1  ;
            STA TOTAL+1
   
            INY     
            INX     
          UNTIL ZERO     
             RTS     
         
     ZEROS100  ; ZEROS $100 bytes at PNTR for begining counts     
             LDA # 0     
             TAY     
             BEGIN            \ ASSUMES CNTZ MODULO 4 = 0     
               STA(PNTR),Y     
               INY     
             UNTIL ZERO
             INC PNTR+1     
             RTS     
         


Top
 Profile  
Reply with quote  
PostPosted: Mon Dec 26, 2016 2:10 am 
Offline

Joined: Tue Jun 08, 2004 11:51 pm
Posts: 213
Finally got a debugged version.

I had a friend help debug it. It is intended to work with a specific
assembler but should only require minor edits to make it work.
There is quite a bit of zero page, that may be difficult for some
machines. I had a number of dumb errors.

If a number of the 2 byte pointers are reused once they are not
needed for the different phases, it won't be too bad.
As I recall, it is a little more than half the size.

It is tuned for fixed sizes of arrays. For larger arrays, it is
faster to just pad the array with a constant value, rather than
trying to make it do smaller amounts.
It can be trimmed to do 512 16 bit integers without too much trouble
but as one approaches around 100 or so, it is best to use the quick
sort.
Otherwise it is not as efficient. It really shows its power on larger
arrays.
This sort does a signed sort but could easily do unsigned by changing
the second:
LDY # $80
JSR MKPNTR
to:
LDY # 0
JSR MKPNTR

For those not familar with the the $80, it just means the HEX value
of 128 decimal.

Some of the label names are in lower case to avoid keyword conflicts
with the assembler used.
This assembler used ; to indicate a comment.

I'm sure someone a little better than me can find some optimizations
in the code. I know a few places, one could remove a few # 0 loads
but I left most in because it makes it easier to modify for different
sizes of arrays to sort.

So, if anyone tells you that QuickSort is the fastest, you can easily
prove them wrong. Just chalange them to a contest of sorts.
Dwight


Code:
    ;  These arrays should all be assigned on $100 boundaries!!!!!
     data    = $3000 ; 1k words of unsorted data input and sorted output
     BUFF    = $3800 ; 1k words for intermediate storage
     DSIZE   = $400  ; words
                ; counter arrays are split for convenience
     LCPLoc  = $4800 ; LSBs counter and pointer
     LCPLocH = $4900 ; LSBs counter and pointer high
     MCPLoc  = $4A00 ; MSBs counter and pointer
     MCPLocH = $4B00 ; MSBs counter and pointer high
 ; CNTZ    EQU 100   ; number of words in pointers
 ; ZERO PAGE ASSIGNMENTS
     FROMPNTR = $70 ;  fetch pointer
     topntr   = $72 ;  to pointer for moves
     LPNTR    = $74 ;   pointer to LSB counter and output
     LPNTRH   = $76
     MPNTR    = $78 ;   pointer to MSB counter and output
     MPNTRH   = $7A
     PNTRL    = $7C ;     General purpose
     PNTRH    = $7E ;     General purpose
     TEMP     = $80 ; 16 BIT IF NEEDED
     total    = $82 ; 16 BIT
     PNTR     = $84
     TEMPY    = $86
     TEMPX    = $87
     ; next available $88

     .DISP_SORT
     .INITS
             CLD
             LDX # 0     ; assumes $100 aligned and consecutive
             STX PNTR
             LDX # LCPLoc/$100
             STX PNTR+1
             JSR ZEROS100
             JSR ZEROS100
             JSR ZEROS100
             JSR ZEROS100
    .DOCNTS  LDX # 0   ; setup from DATA as input values
             STX FROMPNTR
             LDY # data/$100
             STY FROMPNTR+1
             STX LPNTR
             LDY # LCPLoc/$100
             STY LPNTR+1
             STX LPNTRH
             LDY # LCPLocH/$100
             STY LPNTRH+1
             STX MPNTR
             LDY # MCPLoc/$100
             STY MPNTR+1
             STX MPNTRH
             LDY # MCPLocH/$100
             STY MPNTRH+1
             LDX #DSIZE*2/$100 ; How many $80 16 bit value loops to do
             CLC
               LDY #0  ; is the to index
               STY TEMPY
;            BEGIN    ;  needs 8 loop to do $400 words or $800
             .loop1
;              BEGIN   ; Over $100 but only $80 words
               .loop2
                 CLC
                 LDY TEMPY        ; Y is even for LSBs
                 LDA (FROMPNTR),Y ; first LSBs value
                 TAY
                 LDA # 1
                 ADC (LPNTR),Y
                 STA (LPNTR),Y
;                IF CARRY
                 BCC nocarry1
                   LDA # 0
                   ADC (LPNTRH),Y ; notice how these arrays are split.
                                  ; It reduces the amount of Y fiddling
                   STA (LPNTRH),Y ;  at no extra cost in space
                 .nocarry1
;                ENDIF
                 INC TEMPY
                 LDY TEMPY        ; Y is odd  for MSBs
                 LDA (FROMPNTR),Y ; now MSB
                 TAY
                 LDA # 1
                 ADC (MPNTR),Y
                 STA (MPNTR),Y
;                IF CARRY
                 BCC nocarry2
                   LDA # 0
                   ADC (MPNTRH),Y
                   STA (MPNTRH),Y
                 .nocarry2
;                ENDIF
                 INC TEMPY  ; Y is even
               BNE loop2
;              UNTIL ZER0
               ; ONLY DID 1/4 of DATA for each loop
                INC FROMPNTR+1
               DEX
             BNE loop1
;            UNTIL ZERO      ; do the rest
     ; COUNTS ARE DONE
     ; now change the counters to pointers
     .CONVRT2PNTRS
             ; LSB counters to pointers
             LDX # 0
             STX PNTRL
             LDY # LCPLoc/$100
             STY PNTRL+1
             STX PNTRH
             LDY # LCPLocH/$100
             STY PNTRH+1
             STX total
             LDY # BUFF/$100
             STY total+1
             LDY # 0  ; no sign offset for LSBs
             JSR MKPNTR
             ; Now MSB counter to pointers
             LDX # 0
             STX PNTRL
             LDY # MCPLoc/$100
             STY PNTRL+1
             STX PNTRH
             LDY # MCPLocH/$100
             STY PNTRH+1
             STX total
             LDY # data/$100
             STY total+1
             LDY # $80  ; does signed by starting at the center
             JSR MKPNTR
     ; Now LCPLoc and MCPLoc have the pointers to move data.
             LDX # 0
             STX PNTRL
             LDY # LCPLoc/$100
             STY PNTRL+1
             STX PNTRH
             LDY # LCPLocH/$100
             STY PNTRH+1
             STX FROMPNTR
             LDY # data/$100
             STY FROMPNTR+1
             STX topntr
             LDY # BUFF/$100
             STY topntr+1
             LDY # 0         ; DATA OFFSET FOR MSB AND LSB
             JSR moveit
             LDX # 0
             STX PNTRL
             LDY # MCPLoc/$100
             STY PNTRL+1
             STX PNTRH
             LDY # MCPLocH/$100
             STY PNTRH+1
             STX FROMPNTR
             LDY # BUFF/$100
             STY FROMPNTR+1
             STX topntr
             LDY # data/$100
             STY topntr+1
             LDY # 1  ; DATA OFFSET FOR MSB AND LSB
             JSR moveit
;    DONE    JMP DONE ; replace with RTS if called from someplace
             RTS
     ; subroutines

     .moveit     ; used to move items from DATA to BUFF and back
          LDX # DSIZE*2/$100
;         BEGIN  ; 8 times
          .loop3
            ; FETCH POINTER AND PUT IN TOPNTR
            ; INCREMENT THE POINTER BY 2
            ; MOVE THE @ FROMPNTR TO @ TOPNTR
            STX TEMPX
            LDX # $80
;           BEGIN ; $80 times over $100 address
            .loop4
              STY TEMPY
              LDA (FROMPNTR),Y   ; Y is 0 or 1 depending on LSB or MSB poi
              TAY
              LDA (PNTRL),Y
              STA topntr
              LDA (PNTRH),Y
              STA topntr+1
              ; INCREMENT THAT POINTER LOCATION BY 2
              CLC
              LDA (PNTRL),Y
              ADC # 2   ;  ALWAYS EVEN SO ONLY SECOND ADD MAKES CARRY
              STA (PNTRL),Y
;             IF CARRY
              BCC nocarry3
                LDA (PNTRH),Y
                ADC # 0
                STA (PNTRH),Y
              .nocarry3
;             ENDIF
              ; MOVE THE @ FROMPNTR TO @ TOPNTR
              LDY # 0
              LDA (FROMPNTR),Y
              STA (topntr),Y
              INY
              LDA (FROMPNTR),Y
              STA (topntr),Y
              LDA FROMPNTR
              ADC # 2
             STA FROMPNTR
;             IF CARRY
              BCC nocarry4
                INC FROMPNTR+1
              .nocarry4
;             THEN
              LDY TEMPY
              INX
            BNE loop4
;           UNTIL ZERO
            LDX TEMPX
            DEX
          BNE loop3
;         UNTIL ZERO
          RTS
     .MKPNTR   ; X IS NUMBER TO DO    Y IS FIRST ADDRESS, 0 OR $80
          CLC
;         BEGIN     ; $100 times
          .loop5
            LDA (PNTRH),Y
            STA TEMP+1
            LDA total+1
            STA (PNTRH),Y
            LDA (PNTRL),Y
            STA TEMP
            LDA total
            STA (PNTRL),Y
            ADC TEMP
            STA total
            LDA total+1
            ADC TEMP+1  ; no carry here
            STA total+1
            LDA total
            ADC TEMP
            STA total
            LDA total+1
            ADC TEMP+1  ; no carry here
            STA total+1
            INY
            INX
          BNE loop5
;         UNTIL ZERO
             RTS
     .ZEROS100  ; ZEROS $100 bytes at PNTR for begining counts
             LDA # 0
             TAY
;            BEGIN            ; ASSUMES CNTZ MODULO 4 = 0
             .loop6
               STA(PNTR),Y
               INY
             BNE loop6
;            UNTIL ZERO
             INC PNTR+1
             RTS


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 11 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 7 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: