      ====================================================================
	DR  6502    AER 201S Engineering Design 6502 Execution Simulator
      ====================================================================

      Supplementary Notes                                   By: M.J.Malone


			  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.

;==============================================================================
;                 Coding Examples for the Students of AER201S
;==============================================================================
;
;<===  Note the semicolon is a comment indicator
;
.ORG $E000
	   SEI             ; INITIALIZING THE STACK POINTER
	   LDX #$FF
	   TXS
;
	   LDX #$00        ; Initial delay to allow spurious Resets to
	   LDY #$00        ; to subside.  At this point accept that this code
Delay      DEX             ; must appear at the beginning of every EPROM
	   BNE Delay       ; that will ever be used for the 6502 project board.
	   DEY
	   BNE Delay
;
;  We are now ready to try some simple examples
;
;
;  1) Add the numbers $65 and $27 and place the answer in the memory
;     location 'ANSWER'.
;
; First we must assign the location to the label  'ANSWER'
;
ANSWER = $0000
;
; OK now we do the addition:
	   LDA #$65       ; Load the number (#) $65 into the accumulator.
	   CLC            ; Clear the carry flag to prevent carries from a
			  ; previous and unrelated computation.
	   ADC #$27       ; Add the number (#) $27, the result goes in the
			  ; accumulator
	   STA ANSWER     ; Store the result into the memory location ANSWER
;
; Remarks:  Note that the # number sign preceded the numbers $65 and $27 to
;     indicate that these were in fact CONSTANTS, NUMBERS.  If the # sign were
;     omitted, TASM would interpret LDA $65 to mean 'load the accumulator from
;     the memory location $0065'.
;           Looking back at the assignment of ANSWER, we could have said:
;     ANSWER = $00.  This, when used in the statement STA ANSWER would still
;     be interpreted as referring to the memory location $0000 but it would
;     allow the 6502 to use something called 'Zero Page' addressing, a faster
;     method of accessing the memory locations between $0000-$00FF.
;
;
;
 
 
 
 
                                                            page 2 
 
; 2) Subtract the number $27 from the number $65 and store the result in the
;    memory location 'ANS2'.
;
ANS2 = $01   ; We will use zero page addressing to refer to ANS2
;
	   LDA #$65       ; Load the number (#) $65 into the accumulator
	   SEC            ; Clear the C flag (used as the borrow flag in
			  ; subtraction) to prevent borrows from a previous
			  ; unrelated computation.
	   SBC #$27       ; Subtract the number (#) $27 from the accumulator
			  ; the result will be in the accumulator.
	   STA ANS2       ; Store the result in the memory location 'ANS2'
;
; Remarks:  Note that the carry or borrow flag has a inverse logic in the case
;     of subtraction: You have to SEC set the carry flag to prevent a borrow.
;
;
;
; 3)  Program a subroutine to turn on specific bits in on VIA 1, Port A which
; can be used to light LEDs  to  monitor  program  performance.   We  will
; assume that there are 8 LEDs connected to Port A.
;
; We must first initialize port A as an output port
;
	   LDA #%11111111     ; All ones means all bits are outputs
	   STA $A003          ; $A003 is the address of VIA1 Port A, data
			      ; direction register.  This register determines
			      ; whether a bit is input or output.
	   LDA #%00000000     ;
	   STA $A001          ; $A001 is the address of VIA1 Port A I/O
			      ; register.  It is initialized to all zeros
			      ; to mean all bits output 0 volts.
 
; Before we proceed with writing the subroutine we need to send the program
; to a point somewhere after the subroutine we are about to write.  We will
; use a JuMP statement:
;
	   JMP Down_Past  ; Down_Past is a program position label we will
			  ; define later.
;
;
;
;
; ============================================================================
;  It is a good idea to put these bars in to make subroutines obvious
; ============================================================================
;
; Ok know we need to have some Specifications for this subroutine:
;
;  Subroutine Name:  Show
;  Input Registers:  .A  contains a '1' in the bit position that you want to
;                        have turned on
;  Output Registers: None
;
Show       ORA $A001      ; 'Show' against the margin indicates a program
			  ; position label.  ORA $A001 takes the bit pattern
			  ; in .A and logically OR's it with the pattern of
			  ; bits in memory location $A001, the VIA 1, Port A
			  ; I/O register.
;
 
 
 
 
                                                            page 3 
 
; Say $A001 contains the bits:  %abcdefgh  (a through h are unknown 0 or 1)
; and we or it with .A :     OR %00001000
;                           -------------
; We will get:                  %abcd1fgh
;
; Because:   0 or 0 = 0,  1 or 0 = 1,  0 or 1 = 1,  1 or 1 = 1
;   the following is true:  u or 0 = u   and   u or 1 = 1
;   where u is an unknown level.
;
	   STA $A001      ; Store the new bit levels back into the I/O Port
	   RTS            ; Return from Subroutine
;
; Remarks:  This subroutine can be called by setting specific bits in the .A
;   register and calling the subroutine:
;          LDA #%00000001  ; Set bit 0
;          JSR Show        ; Show this on the VIA port
;
;           Subroutines can be nested IE one subroutine can call others.  Care
;   should be exercised when one subroutine calls itself because there are no
;   'local' variables in assembly language (unless you simulate them) since
;   the memory in the 6502 is global to all programs or subroutines.
;   Subroutines can significantly compact a program and can lend to readability
;   of the code if properly documented.
;
;
;
Down_Past          ; This is the program position label that marks where the
		   ; JMP Down_Past goes to.
;
;
; 4) Now that we have done an output subroutine, lets do some comparisons and
;    light leds to show the results.  Check if ANSWER - ANS2 = 2*#$27.
;
RHS = $03         ; Stores the value of the right hand side of the equation
;
	   LDA ANSWER    ; Calculate the RHS
	   SEC
	   SBC ANS2
	   STA RHS
;
	   LDA #$27      ; To calculate 2*#$27 you use #$27+#$27
	   CLC
	   ADC #$27      ; Got the LHS in the accumulator
;
	   CMP RHS
	   BNE Not_equal ; Don't Show any LED's
;
; The equation is true, light LED connected to bit 0
	   LDA #%00000001
	   JSR Show
;
Not_Equal
;
;
;
 
 
 
 
 
 
 
 
 
                                                            page 4 
 
; 5)  See if ANSWER and ANS2 have any bits in common;  light LED 1 if they do.
;
	   LDA ANSWER
	   AND ANS2      ; AND Tests to see if a bit in both arguments is
			 ; set.  If it is the resulting bit is set, otherwise
			 ; the resulting bit is cleared.
			 ; If two arguments have no bits in common the result
			 ; will have no bits set or will be zero.  In this case
			 ; the AND instruction will set the zero flag.
	   BEQ No_Bits   ; The BEQ branches on result equal for comparisons
			 ; or result zero for arithmetic and logical
			 ; OpCodes.
	   LDA #%00000010
	   JSR Show      ; This turns on bit 1 if there were any bits in common
;
; There were no bits in common, the AND resulted in a Z=1, zero
No_Bits
;
;
;
; 6) See if ANSWER and ANS2 have bit #1 in common; light LED 2 if they do.
;
	   LDA ANSWER
	   AND #%00000010  ; This picks off the value of bit 1.  You can think
			   ; of a 1 in a constant of an AND statement like a
			   ; delta function that zeros picks off one value
			   ; and zeros the rest of the domain.  As a result
			   ; ANDing with #%11111111 does not change a number.
	   AND ANS2        ; We know that the .A has all zeros except possibly
			   ; bit 1.  ANDing with ANS2 will result in zero
			   ; unless bit 1 was set in both ANSWER and ANS2
	   BEQ Bit1_Not_Set  ; If the result is Z=1, don't show LEDs
	   LDA #%00000100  ; otherwise Show LED 2
	   JSR Show
;
Bit1_Not_Set
;
;
;
; 7) Do an endless loop to alternate the pattern of indicators now present
; on the LEDs with the binary representation of ANSWER.
;
Endless    LDX $A001       ; Grab the present bit pattern
	   LDA ANSWER      ; Grab the new bit pattern
	   STA $A001       ; Put the new pattern on the Port
	   STX ANSWER      ; Put the old pattern into ANSWER
;
	   LDX #$00
	   LDY #$00
D1         DEX             ; A double indexed wait loop to waste time
	   BNE D1
	   DEY
	   BNE D1
	   JMP Endless     ; Next time the old bit pattern becomes the new
			   ; by  the  way it was stored, rotating through
			   ; the ANSWER==>.A==>Port==>.X==>ANSWER loop.
;
 
 
 
 
 
 
 
                                                            page 5 
 
; The last entry in every program must  set  the  reset  vector  to  point
; to  the  beginning  of  the  program.  If there is an interrupt routine
; then the interrupt vector must be set as well.  In this  case  there  is
; only a main program.
;
.ORG $FFFC                 ; Set pointer to Reset Vector Location
.WORD $E000                ; Store $E000 as the reset vector
.END
