GENWiki

Premier IT Outsourcing and Support Services within the UK

User Tools

Site Tools


archive:programming:exam2_65

Table of Contents

    ====================================================================
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.  The following are the basic routines used
    in a stack based mathematics system very similar to that used in the
    FORTH  or  PostScript languages.  It is a good example of addressing
    modes and use and reuse of the most common  6502  instructions.   It
    introduces  the user to the assembly language level maintenance of a
    stack, movement of data and use of the zero page.  Note there may be
    errors in the code, it is  not  intended  that  it  be  cut  up  and
    included  in  students  files.  It is intended only as an example of
    addressing modes and instructions.

;

; Coding Examples for the Students of AER201S ;

; ; .ORG $E000

   SEI             ; INITIALIZING THE STACK POINTER
   LDX #$FF
   TXS

;

   LDX #$00        ; Initial
   LDY #$00

Delay DEX

   BNE Delay
   DEY
   BNE Delay

; ; ;

; Definitions and memory allocation ;

; Start_Page = $10 ; Stack goes from $1000-$1FFF or pages $10-$20 End_Page = $20 ; Stack_Ptr = $FE ; Address of the pointer to the next free byte in

		   ; the stack

Memory_Ptr = $FC ; Address of a pointer to a piece of data in

		   ; memory

MTemp = $FB ; Temporary Variable used in memory routines MTemp1 = $FA ; Temporary Variable used in memory routines ; Reg_Len = $08 ; Use 8 byte utility registers ; Utl_Reg0 = $00 ; Utility Register 0 Used for Math and stack Utl_Reg1 = Utl_Reg0+Reg_len ; Utility Register 1 manipulations Utl_reg2 = Utl_Reg1+Reg_Len ; Utility Register 2 ; ; ;

page 2

LDA #Start_Page ; Initialize the stack pointer to point to the

   STA Stack_Ptr+1  ; first byte of the space allotted to be stack
   LDA #$00         ; space
   STA Stack_Ptr

;

   JMP Main         ; Jump to the main program, what follows are
		    ; subroutines

; ; ; ; ;

; Halt execution ;

; Halt JMP Halt ; In case of an error, the program jumps here ; ; ; ; ; ; ;

; Stack Maintenance Subroutines ;

; ; ; ;

; Will a (.A) byte long number pushed into the stack overflow the stack? ;

; ; Call Name: Overrun ; ; Input Variables: .A Holds the number of bytes you want to push onto the ; stack ; ; Output Variables: None. The Routine stops execution when an overflow ; occurs. Ideally it would call an error trap routine ; and give some output. ; Overrun CLC

      ADC Stack_Ptr     ; Add the number of bytes to the current
      BCS Try_Page      ; stack pointer low byte - if less than a page
      RTS               ; then it could not have overrun.

Try_Page LDA #$01 ; It overrun a page, check to see if the next

      ADC Stack_Ptr+1   ; page is part of the stack area.
      CMP #End_Page
      BEQ Halt          ; If it has overrun then Halt!
      RTS               ; otherwise RTS - everything is OK

; ; ; ;

page 3

;

; Will a (.A) byte long number pulled from the stack underflow the stack? ;

; ; Call Name: Underrun ; ; Input Variables: .A Holds the number of bytes you want to pull from the ; stack ; ; Output Variables: None. The Routine stops execution when an underflow ; occurs. Ideally it would call an error trap routine ; and give some output. ; Underrun STA MTemp

      LDA Stack_Ptr     ; Subtract the number of bytes from the stack
      SEC               ; pointer.
      SBC MTemp
      BCC Try_Page      ; If it has not underrun an page, then
      RTS               ; RTS - everything is OK

Try_Page LDA Stack_Ptr+1 ; It has underrun a page - check to see if

      SBC #$00          ; the previous page is part of the stack.
      CMP #Start_Page
      BMI Halt          ; If not then Halt - there was an underrun

; The BMI instruction assumes the stack will never be allowed 32K. It assumes ; the 'N' flag will never be set from comparing two numbers more different ; then $80 resulting from a stack of $8000 length or more - 32K

      RTS

; ; ; ; ;

; Copy .Y bytes of data from the memory pointer to the stack ;

; ; Call Name: Mem_to_Stk ; ; Input Variables: .Y is the number of bytes of memory to move to the stack ; Memory_Ptr points to the first address of the piece of data ; ; Output Variables: None. ; ; Mem_to_Stk TYA

      JSR Overrun           ; Check for a Stack Overrun
      STY MTemp             ; Store #bytes temporarily
      LDY #$00

F_Ag LDA (Memory_Ptr),y ; Move data from Memory to

      STA (Stack_Ptr),y     ; stack
      INY
      CPY MTemp
      BNE F_Ag              ; until .Y=#bytes

;

      LDA MTemp             ; Add the number of bytes to the stack
      CLC                   ; pointer so that it points to the next
      ADC Stack_Ptr         ; free byte of stack space

page 4

STA Stack_Ptr

      LDA #$00
      ADC Stack_Ptr+1
      STA Stack_Ptr+1
      RTS

; ; ; ; ;

; Copy .Y bytes of data from the stack to the memory pointer ;

; ; Call Name: Stk_To_Mem ; ; Input Variables: .Y is the number of bytes of stack data to move to memory ; Memory_Ptr points to the first address of the piece of data ; ; Output Variables: None. ; Stk_To_Mem TYA

      JSR Underrun          ; Check for a Stack Underrun
      STY MTemp             ; Store #bytes temporarily
      LDA Stack_Ptr         ; Subtract to find first address of
      SEC                   ; a .Y byte length piece of data in the
      SBC MTemp             ; stack.  Nothing prevents the user from
      STA Stack_Ptr         ; pulling a different size data piece
      LDA Stack_Ptr+1       ; from the stack than was pushed in.  In
      SBC #$00              ; fact that makes the stack useful in
      STA Stack_Ptr+1       ; doing string manipulations.

;

      LDY #$00

T_Ag LDA (Stack_Ptr),y ; Move data from the stack

      STA (Memory_Ptr),y    ; to memory
      INY
      CPY MTemp
      BNE T_Ag              ; until .Y=#bytes

;

      RTS

; ; ; ; ;

; Copy .Y bytes of data from the memory pointer to the Utl_Reg(.X) ;

; ; Call Name: Mem_to_Reg ; ; Input Variables: - .Y is the number of bytes of memory to move ; to Utl_Reg(.X) from a location pointed to by ; Memory_Ptr ; - .X is the number of the Utility register ; - Memory_Ptr points to the first address of the piece of ; data ;

page 5

; Output Variables: None. ; Mem_to_Reg CPX #$03 ; .X must be less than 3

      BPL JHalt
      CPY #Reg_Len+1        ; .Y must be less than (Reg_Len+1)
      BPL JHalt
      JMP MR_Cont

JHalt JMP Halt MR_Cont TXA

      STY MTemp             ; Store #bytes temporarily

; ; The following assumes Reg_Len=8 and must be adjusted otherwise ;

      CLC
      ASL A                 ; Multiply .X by 8 to get the
      ASL A                 ; first address of the Utl_Reg(.X)
      ASL A

;

      STA MTemp1            ; Store the beginning address
      ADC MTemp             ; Add the length of Number
      STA MTemp             ; Store the ending of move address

;

      LDX MTemp1            ; Load address of beginning of data
      TXA                   ; on zero page (by .X index offset)
      CLC
      ADC #Reg_Len          ; Add on the length of the register to
      STA MTemp1            ; find the end of the register

;

      LDY #$00

MR_Ag LDA (Memory_Ptr),Y ; Move Data from Memory_Ptr

      STA Utl_Reg0,X        ;   to the Utl_Reg
      INY
      INX
      CPX MTemp             ; Until .X=end of move address
      BNE MR_Ag

;

      LDA #$00

MR_Zero CPX MTemp1 ; While the entire Utl_Reg is not

      BEQ MR_Done           ; yet full (not reached end of register),
      STA Utl_Reg0,X        ; Put #$00's in the rest of the locations
      INX
      JMP MR_Zero

; MR_Done RTS ; ; ; ; ;

; Copy .Y bytes of data from Utl_Reg(.X) to the memory pointer ;

; ; Call Name: Reg_to_Mem ;

page 6

; Input Variables: - .Y is the number of bytes of register data to move ; to memory ; - .X is the register number ; - Memory_Ptr points to the first address of the piece of data ; ; Output Variables: None. ; Reg_to_Mem CPX #$03 ; .X must be less than 3

      BPL JHalt
      CPY #Reg_Len+1        ; .Y must be less than Reg_Len+1
      BPL JHalt
      JMP RM_Cont

JHalt JMP Halt RM_Cont TXA

      STY MTemp             ; Store #bytes temporarily

; ; The following assumes Reg_Len=8 and must be adjusted otherwise ;

      CLC
      ASL A                 ; Multiply .X by 8 to get the
      ASL A                 ; first address of the Utl_Reg(.X)
      ASL A

;

      STA MTemp1            ; Store the beginning address
      ADC MTemp             ; Add the length of Number
      STA MTemp             ; Store the ending address

;

      LDX MTemp1            ; Load address of beginning of data
      LDY #$00

RM_Ag LDA Utl_Reg0,X ; Move data from Utl_Reg

      STA (Memory_Ptr),Y    ;  to the Memory_Ptr
      INY
      INX
      CPX MTemp             ; Until .X=end address
      BNE RM_Ag

RTS ; ; ; ; ;

; Copy .Y bytes of data from the stack pointer to the Utl_Reg(.X) ;

; ; Call Name: Stk_to_Reg ; ; Input Variables: - .Y is the number of bytes of memory to move ; to Utl_Reg(.X) from a location pointed to by ; Memory_Ptr ; - .X is the number of the Utility register ; - Memory_Ptr points to the first address of the piece of ; data ; ; Output Variables: None. ;

page 7

Stk_to_Reg CPX #$03 ; .X must be less than 3

      BPL JHalt
      CPY #Reg_Len+1        ; .Y must be less than Reg_Len+1
      BPL JHalt
      JMP SR_Cont

SRHalt JMP Halt ; SR_Cont TYA

      JSR Underrun          ; Check for a Stack Underrun
      STY MTemp             ; Store #bytes temporarily
      LDA Stack_Ptr         ; Subtract to find first address of
      SEC                   ; a .Y length data element in the stack
      SBC MTemp
      STA Stack_Ptr
      LDA Stack_Ptr+1
      SBC #$00
      STA Stack_Ptr+1

;

      TXA

; ; The following assumes Reg_Len=8 and must be adjusted otherwise ;

      CLC
      ASL A                 ; Multiply .X by 8 to get the
      ASL A                 ; first address of the Utl_Reg(.X)
      ASL A

;

      STA MTemp1            ; Store the beginning address
      ADC MTemp             ; Add the length of Number
      STA MTemp             ; Store the ending of move address

;

      LDX MTemp1            ; Load address of beginning of data
      TXA
      CLC
      ADC #Reg_Len          ; Add on the length of the register
      STA MTemp1            ; to find the last address and store it

;

      LDY #$00

SR_Ag LDA (Stack_Ptr),Y ; Move Data from Memory_Ptr

      STA Utl_Reg0,X        ;   to the Utl_Reg
      INY
      INX
      CPX MTemp             ; until .X=end of move address
      BNE MR_Ag

;

      LDA #$00

SR_Zero CPX MTemp1 ; While the entire 8 byte Utl_Reg is not

      BEQ SR_Done           ; yet full (not at last address),
      STA Utl_Reg0,X        ; Put Zero's in the higher order locations
      INX
      JMP SR_Zero

; SR_Done

      RTS

; ; ; ;

page 8

;

; Copy .Y bytes of data from Utl_Reg(.X) to the stack pointer ;

; ; Call Name: Reg_to_Stk ; ; Input Variables: - .Y is the number of bytes of register data to move ; to memory ; - .X is the register number ; - Memory_Ptr points to the first address of the piece of data ; ; Output Variables: None. ; Reg_to_Stk CPX #$03 ; .X must be less than 3

      BPL JHalt
      CPY #Reg_Len+1        ; .Y must be less than Reg_Len+1
      BPL JHalt
      JMP RM_Cont

JHalt JMP Halt RM_Cont TXA

      STY MTemp             ; Store #bytes temporarily

; ; The following assumes Reg_Len=8 and must be adjusted otherwise ;

      CLC
      ASL A                 ; Multiply .X by 8 to get the
      ASL A                 ; first address of the Utl_Reg(.X)
      ASL A

;

      TAX                   ; Store the beginning address
      ADC MTemp             ; Add the length of move
      STA MTemp1            ; Store the end of move address

;

      LDY #$00

RM_Ag LDA Utl_Reg0,X ; Move data from Utl_Reg

      STA (Memory_Ptr),Y    ;  to the Memory_Ptr
      INY
      INX
      CPX MTemp1            ; Until .X=end of move address
      BNE RM_Ag

;

      LDA MTemp             ; Take the number of bytes moved and add
      CLC                   ; it to the old stack pointer to make it
      ADC Stack_Ptr         ; point at the next free byte of stack
      STA Stack_Ptr         ; space
      LDA #$00
      ADC Stack_Ptr+1
      STA Stack_Ptr+1

RTS ; ; ; ;

page 9

;

; Mathematics Subroutines ;

; ; We will assume that all one byte manipulations can be handled in the ; user software or in user subroutines and any address calculations IE ; 2 byte math can be done most quickly by specialized user routines. ; Here then are a basic set of single precision and 4 byte integer math ; subroutines. ; ; Storage format: ; ; Offset of byte: +3 +2 +1 0 ; ; Integer: SIIIIIII IIIIIIII IIIIIIII IIIIIIII S-Sign bit ; I-Integer bits ; ; Single: EEEEEEEE SMMMMMMM MMMMMMMM MMMMMMMM E-Exponent bits ; / S-Mantissa Sign ; Decimal Point M-Mantissa Bits ; ; In single precision storage, the exponent is offset by $80 and the ; mantissa is assumed to be normalize so that the mantissa begins with ; %1.MMMMMMM… . The '1' is omitted and the decimal point is assumed ; leading to one more bit of significance. IEEE single precision ; format has the sign bit precede the 8 exponent bits however this leads ; to the exponent bits not being aligned on an even byte. Since this ; would slow manipulations of the numbers on an 8 bit computer, ; requiring the exponent to be reassembled each time, it is not used ; here. ; ; Sign1 = $F9 ; Variables that keep track of the sign bits of the Sign2 = $F8 ; two arguments and the answer Ans_Sign = $F7 ; ; Exp1 = $F6 ; Variables to hold the exponent bytes of the arguments Exp2 = $F5 ; and either the common exponent (used in add and Com_Exp = $F4 ; subtract) or the answer's exponent. ; ; ;

; Move Utl_Reg2 to Utl_Reg0 (4 byte) ;

; ; Call name: Two_to_0 ; ; No Input or Output variables ; Two_to_0

      LDA Utl_Reg2
      STA Utl_Reg0
      LDA Utl_Reg2+1
      STA Utl_Reg0+1
      LDA Utl_Reg2+2

page 10

STA Utl_Reg0+2

      LDA Utl_Reg2+3
      STA Utl_Reg0+3
      RTS

; ; ; ; ;

; Move Utl_Reg2 to Utl_Reg1 (4 byte) ;

; ; Call name: Two_to_1 ; ; No Input or Output variables ; Two_to_1

      LDA Utl_Reg2
      STA Utl_Reg1
      LDA Utl_Reg2+1
      STA Utl_Reg1+1
      LDA Utl_Reg2+2
      STA Utl_Reg1+2
      LDA Utl_Reg2+3
      STA Utl_Reg1+3
      RTS

; ; ; ; ;

; Internal Addition Routine ;

; ; Simple add of Utl_Reg2=Utl_Reg0 + Utl_Reg1 with no sign considerations ; In_Add

      CLC
      LDA Utl_Reg0
      ADC Utl_Reg1
      STA Utl_Reg2
      LDA Utl_Reg0+1
      ADC Utl_Reg1+1
      STA Utl_Reg2+1
      LDA Utl_Reg0+2
      ADC Utl_Reg1+2
      STA Utl_Reg2+2
      LDA Utl_Reg0+3
      ADC Utl_Reg1+3
      STA Utl_Reg2+3
      RTS

; ; ; ;

page 11

;

; Internal Subtraction Routine ;

; ; Simple subtract of Utl_Reg2=Utl_Reg0 - Utl_Reg1 with no sign considerations ; In_Subt

      SEC
      LDA Utl_Reg0
      SBC Utl_Reg1
      STA Utl_Reg2
      LDA Utl_Reg0+1
      SBC Utl_Reg1+1
      STA Utl_Reg2+1
      LDA Utl_Reg0+2
      SBC Utl_Reg1+2
      STA Utl_Reg2+2
      LDA Utl_Reg0+3
      SBC Utl_Reg1+3
      STA Utl_Reg2+3
      RTS

; ; ; ; ;

; Internal Reverse Subtraction Routine ;

; ; Simple subtract of Utl_Reg2=Utl_Reg1 - Utl_Reg0 with no sign considerations ; In_R_Subt

      SEC
      LDA Utl_Reg1
      SBC Utl_Reg0
      STA Utl_Reg2
      LDA Utl_Reg1+1
      SBC Utl_Reg0+1
      STA Utl_Reg2+1
      LDA Utl_Reg1+2
      SBC Utl_Reg0+2
      STA Utl_Reg2+2
      LDA Utl_Reg1+3
      SBC Utl_Reg0+3
      STA Utl_Reg2+3
      RTS

; ; ; ; ;

; Integer 4 byte Add ;

; ; Call Name: IADD4 ;

page 12

; Input Variables: The two numbers to be added are assumed to be in Utl_Reg0 ; and Utl_Reg1 ; ; Output Variables: The answer appears in Utl_Reg2. ; ;


			    .
			    .
			    .
	 The remainder of the file has been omitted.
			    .
			    .
			    .

——————————————————————————- ; ; ; .ORG $FFFC .WORD $E000 .END <eof> 

/data/webs/external/dokuwiki/data/pages/archive/programming/exam2_65.txt · Last modified: 2000/12/16 02:37 by 127.0.0.1

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki