Advanced 6502 Assembly Code Examples.txt

(22 KB) Pobierz
      ====================================================================
	DR  6502    AER 201S Engineering Design 6502 Execution Simulator
      ====================================================================

      Supplementary Notes                                   By: M.J.Malone


		       Advanced 6502 Assembly Code Examples
		       ====================================

	   The remainder of this file will be in a  format  acceptable  to
      TASM  for direct assembly.  Note there may be errors in the code, it
      is not intended that it be cut up and included  in  students  files.
      It   is   meant   only   as  an  example  of  addressing  modes  and
      instructions.  The first example is  a  prime  number  finder.   The
      second  example  is  a set of subroutines to maintain a multitasking
      system.


;==============================================================================
;             Advanced Coding Examples for the Students of AER201S
;==============================================================================
;
;
.ORG $E000
	   SEI             ; INITIALIZING THE STACK POINTER
	   LDX #$FF
	   TXS
;
	   LDX #$00
	   LDY #$00
Delay      DEX
	   BNE Delay
	   DEY
	   BNE Delay
;
;=============================================================================
;    Prime Number Finder
;=============================================================================
;  This Prime Number Finder uses the sieve method to find the primes up to 255
;  and then uses those primes to find the primes up to 65535.  Note that this
;  is of course not THE most efficient way to find primes but it makes a good
;  demonstration.
;  It would be neat to stack this code up against a casually written/optimized
;  compiled C prime number finder on a raging 386.  I have a feeling there will
;  be less than a factor of ten difference on execution speed.  You may be
;  surprised just how fast the 6502 is on simple problems.
;
Test_num = $00             ;  Test Number to Eliminate non-primes
Array    = $00             ;  Base Address for the array of primes
;
;
	   lda #$01
	   sta $a003
	   lda #$01
	   sta $a001       ;  Turns on an LED on bit zero of port A of VIA 1
			   ;  to let you know it has started looking for primes
;
 
 
 
 
 
 
 
 
 
                                                            page 2 
 
	   ldx #$01        ;  Initialize the array of numbers
Init_Loop  txa
	   sta Array,x
	   inx
	   bne Init_loop
;
	   lda #$02        ; Initialize the Test_num = 2
	   sta Test_num
	   lda #$04        ; Put the square of 2 in the accumulator
			   ;   as the first non-prime
;
;  Start Setting the Multiples of the Test_num to zero
Start_num
Got_Mult   tax
	   stz Array,x     ; Set multiples of Test_num to zero since they
	   clc             ; are not prime.
	   adc Test_num    ; Calculate the next multiple
	   bcs Next_num    ; Until the Multiples are outside the array
	   jmp Got_Mult
;
Next_num   inc Test_num    ; Go on to the next Test_num
	   ldx Test_num
	   cpx #$10        ; Until Test_num => sqrt(largest number)
	   beq More_Primes
	   lda Array,x
	   beq Next_num    ; Don't use Test_num if Test_num is not prime
	   txa
;    Got a valid new Test_num, now find its square because all non-primes
;       multiples less than its square are eliminated already
	   dex
	   clc
Square     adc Test_num
	   dex
	   bne Square
;    OK Got the square of Test_num in the accumulator
;       lets start checking
	   jmp Start_num
;
;
More_Primes
;
;   Ok now we have all the primes up to 255 in the memory locations $01-$FF
;     Lets repack them more neatly into an array with no spaces to make our
;     life easier
;
	   ldx #$00          ; .X is a pointer into the loose array
	   ldy #$01          ; .Y is a pointer into the packed array
Repack     inx
	   beq Done_packing
	   lda Array,x
	   beq Repack
	   sta Array,y
	   iny
	   jmp Repack
;
 
 
 
 
 
 
 
 
 
                                                            page 3 
 
Prime_Ptr = $F0              ; This is a points into the list of primes greater
			     ;  than $FF and less that $10000
;
Poss_Prime = $F2             ; Possible prime
Temp       = $F4             ; A Temporary Number used to find modulus
Shift      = $F6             ; Number of Places that .A is shifted
TempArg    = $F7             ; A temporary number; argument of modulus
 
;
Done_packing
	   lda #$00          ; Store a $00 at the end of the array of short
	   sta Array,y       ; primes so we know when we have reached the end
	   lda #$00
	   sta Prime_ptr     ; Set the Prime Pointer (for primes >$FF)
	   lda #$02          ; pointing into $0200. The found primes will be
	   sta Prime_ptr+1   ; recorded sequentially from there on.
;
	   lda #$01          ; Start with $0101 as the first possible prime
	   sta Poss_Prime
	   sta Poss_Prime+1
;
Next_PP    ldy #$02
Next_AP    lda Array,y
	   beq Prime
	   jsr Mod
	   beq Next_Poss_prime     ; it was a multiple of Array,y
				   ; and therefore not prime
	   iny
	   jmp Next_AP
;
Prime      ldx #$00
	   lda Poss_prime       ; Store prime away in the array of primes
	   sta (Prime_ptr,x)
	   inx
	   lda Poss_prime+1
	   sta (Prime_ptr,x)
	   clc
	   lda Prime_ptr        ; Increment the pointer in the array of primes
	   adc #$02
	   sta Prime_ptr
	   lda Prime_ptr+1
	   adc #$00
	   sta Prime_ptr+1
;
Next_Poss_prime
	   clc                  ; Increment Poss_Prime to look at the next
	   lda Poss_Prime       ; number
	   adc #$01
	   sta Poss_Prime
	   lda Poss_Prime+1
	   adc #$00
	   sta Poss_Prime+1
	   bcc Next_PP          ; Carry will be set when we reach $10000
;
;   Ends when it has found all the primes up to 65535
;
;
 
 
 
 
 
 
 
                                                            page 4 
 
	   lda #$00
	   sta $a001       ; Turns off the LED after the code finishes
;
DONE       JMP DONE        ; Endless loop at end to halt execution
;
;
;
; --------------------------------------------------------------------------
; Find the Modulus Remainder of Poss_Prime and number in A
; --------------------------------------------------------------------------
; Input Regs: .A Number being divided into the Possible Prime
;             Poss_Prime contains the number being tested for primeness
; Output  Regs:  .A  Modulo remainder
;
Mod           ldx Poss_Prime      ; Transfer Poss_Prime to Temp
	      stx Temp
	      ldx Poss_Prime+1
	      stx Temp+1
	      ldx #$00            ; Set the bit shifting counter to #$00
	      stx Shift
;
;  Compare A to the upper byte of Temp
;
Compare       sec                 ; Compare to see if the .A is greater than
	      cmp Temp+1          ; (equal to) the high byte of Temp
	      bcs A_Bigger
;
;  If the accumulator is smaller than the upper byte of Temp then shift it
;  until it is bigger or it overflows the highest bit
;
	      clc
	      rol a
	      bcc Not_off_end
;
;  It has overflowed the highest bit, unroll it by one position
;
	      ror a
	      sta TempArg
	      jmp Start_Mod
;
;  Not overflowed yet, go and compare it to Temp+1 again
;
Not_off_end   inc Shift
	      jmp Compare
;
;  If the accumulator is bigger and it has been shifted then unshift by one
;  bit
;
A_Bigger      ldx Shift
	      cpx #$00
	      sta TempArg
	      beq Start_Mod
	      clc
	      ror a
	      dec Shift
	      sta TempArg
;
 
 
 
 
 
 
 
                                                            page 5 
 
;  If the accumulator was smaller than the highest byte of Temp it now
;     has been shifted to strip off the high bit at least
;  If the accumulator was larger than the highest byte then proceed with the
;     regular modulus shift and subtracts
;
Start_Mod     lda Temp+1
	      sec
	      cmp TempArg
	      bcc Dont_Subt
;
;  Subtract as a stage of division
;
	      sbc TempArg
	      sta Temp+1
;
Dont_Subt
;
;  We would now like to shift the TempArg relative the Temp
;    1) Shift is greater than zero - accumulator was shifted - unshift it
;    2) Shift Temp - if shift reaches -8 then we are out of Temp and
;       what we have left is the modulus --RTS
;
	      lda Shift
	      bmi Sh_Temp     ; Case 2
	      beq Sh_Temp
;   Case 1
	      clc
	      ror TempArg
	      dec Shift
	      jmp Start_Mod
;
Sh_Temp       cmp #$f8
	      bne Continue
	      lda Temp+1       ;  This is the Modulus
	      rts
 
Continue      dec Shift
	      clc
	      rol Temp
	      rol Temp+1
	      jmp Start_Mod
;
.ORG $FFFC
.WORD $E000
.END
;
;
;
;==============================================================================
;******************************************************************************
;==============================================================================
;
;
 
 
 
 
 
 
 
 
 
 
 
                                                            page 6 
 
;=============================================================================
;  The Multitasking 6502  -  See you 6502 do several things at once
;=============================================================================
;  This relies on the assumption that there is a source of IRQ's out there
;  that is repetitive and each task is allotted time between each IRQ.
;  Process 1 is started automatically by the RESET signal.
;  Any process can extend its life for a while (if it is doing something
;  important) by setting the SEI and then CLI after the important section.
;
;
;
.ORG $E000
	   SEI             ; INITIALIZING THE STACK POINTER
...
Zgłoś jeśli naruszono regulamin