home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-03-20 | 32.2 KB | 331 lines | [TEXT/ALFA] |
-
- Assembly in one step
- --------------------
-
-
- A brief guide to programming the 6502 in assembly language. It will
- introduce the 6502 architecture, addressing modes, and instruction set.
- No prior assembly language programming is assumed, however it is assumed
- that you are somewhat familiar with hexadecimal numbers. Programming
- examples are given at the end. After reading this it is recommended that
- you review the file 6502 INSTRUCTION SUMMARY. Much of this material
- comes from _6502 Software Design_ by Leo Scanlon, Blacksburg, 1980.
-
-
- ================================================================================
-
-
- The 6502 Architecture
- ---------------------
-
- The 6502 is an 8-bit microprocessor that follows the memory oriented
- design philosophy of the Motorola 6800. Several engineers left
- Motorola and formed MOS Technology which introduced the 6502 in 1975.
- The 6502 gained in popularity because of it's low price and became the
- heart of several early personal computers including the Apple II,
- Commodore 64, and Atari 400 and 800.
-
-
- Simplicity is key
- -----------------
-
- The 6502 handles data in its registers, each of which holds one byte
- (8-bits) of data. There are a total of three general use and two special
- purpose registers:
-
-
- accumulator (A) - Handles all arithmetic and logic. The real heart
- of the system.
-
- X and Y - General purpose registers with limited abilities.
-
- S - Stack pointer.
-
- P - Processor status. Holds the result of tests
- and flags.
-
-
- All of the 6502 is implemented in MacQForth with the exception of
- interrupts and decimal mode arithmetic.
-
-
- Stack Pointer
- -------------
-
- When the microprocessor executes a JSR (Jump to SubRoutine)
- instruction it needs to know where to return when finished. The 6502
- keeps this information in low memory from $0100 to $01FF and uses the
- stack pointer as an offset. The stack grows down from $01FF and makes
- it possible to nest subroutines up to 128 levels deep. Not a problem
- in most cases.
-
-
- Processor Status
- ----------------
-
- The processor status register is not directly accessible by any 6502
- instruction. Instead, there exist numerous instructions that test the
- bits of the processor status register. The flags within the register
- are:
-
-
- bit -> 7 0
- +---+---+---+---+---+---+---+---+
- | N | V | | B | D | I | Z | C | <-- flag, 0/1 = reset/set
- +---+---+---+---+---+---+---+---+
-
-
- N = NEGATIVE. Set if bit 7 of the accumulator is set.
-
- V = OVERFLOW. Set if the addition of two like-signed numbers or the
- subtraction of two unlike-signed numbers produces a result
- greater than +127 or less than -128.
-
- B = BRK COMMAND. Set if an interrupt caused by a BRK, reset if
- caused by an external interrupt. Not used in MacQForth.
-
- D = DECIMAL MODE. Set if decimal mode active. Not used in MacQForth.
-
- I = IRQ DISABLE. Set if maskable interrupts are disabled. Not
- used in MacQForth.
-
- Z = ZERO. Set if the result of the last operation (load/inc/dec/
- add/sub) was zero.
-
- C = CARRY. Set if the add produced a carry, or if the subtraction
- produced a borrow. Also holds bits after a logical shift.
-
-
- Accumulator
- -----------
-
- The majority of the 6502's business makes use of the accumulator. All
- addition and subtraction is done in the accumulator. It also handles
- the majority of the logical comparisons (is A > B ?) and logical bit
- shifts.
-
-
- X and Y
- -------
-
- These are index registers often used to hold offsets to memory
- locations. They can also be used for holding needed values. Much of
- their use lies in supporting some of the addressing modes.
-
-
-
- Addressing Modes
- ----------------
-
- The 6502 has 13 addressing modes, or ways of accessing memory. The 65C02
- introduces two additional modes.
-
- They are:
-
-
- +---------------------+--------------------------+
- | mode | assembler format |
- +=====================+==========================+
- | Immediate | #aa |
- | Absolute | aaaa |
- | Zero Page | aa | Note:
- | Implied | |
- | Indirect Absolute | (aaaa) | aa = 2 hex digits
- | Absolute Indexed,X | aaaa,X | as $FF
- | Absolute Indexed,Y | aaaa,Y |
- | Zero Page Indexed,X | aa,X | aaaa = 4 hex
- | Zero Page Indexed,Y | aa,Y | digits as
- | Indexed Indirect | (aa,X) | $FFFF
- | Indirect Indexed | (aa),Y |
- | Relative | aaaa | Can also be
- | Accumulator | A | assembler labels
- +---------------------+--------------------------+
-
- (Table 2-3. _6502 Software Design_, Scanlon, 1980)
-
-
- Immediate Addressing
- --------------------
-
- The value given is a number to be used immediately by the
- instruction. For example, LDA #$99 loads the value $99 into the
- accumulator.
-
-
- Absolute Addressing
- -------------------
-
- The value given is the address (16-bits) of a memory location that
- contains the 8-bit value to be used. For example, STA $3E32 stores
- the present value of the accumulator in memory location $3E32.
-
-
- Zero Page Addressing
- -------------- p
- -----------------
-
- ;
- ; An 8-bit count down loop
- ;
-
- start LDX #$FF ; load X with $FF = 255
- loop DEX ; X = X - 1
- BNE loop ; if X not zero then goto loop
- RTS ; return
-
- How does the BNE instruction know that X is zero? It
- doesn't, all it knows is that the Z flag is set or reset.
- The DEX instruction will set the Z flag when X is zero.
-
-
- ;
- ; A 16-bit count down loop
- ;
-
- start LDY #$FF ; load Y with $FF
- loop1 LDX #$FF ; load X with $FF
- loop2 DEX ; X = X - 1
- BNE loop2 ; if X not zero goto loop2
- DEY ; Y = Y - 1
- BNE loop1 ; if Y not zero goto loop1
- RTS ; return
-
- There are two loops here, X will be set to 255 and count to
- zero for each time Y is decremented. The net result is to
- count the 16-bit number Y (high) and X (low) down from $FFFF
- = 65535 to zero.
-
-
- Other examples
- --------------
-
- ** Note: All of the following examples are lifted nearly verbatim from
- the book "6502 Software Design", whose reference is above.
-
-
- ; Example 4-2. Deleting an entry from an unordered list
- ;
- ; Delete the contents of $2F from a list whose starting
- ; address is in $30 and $31. The first byte of the list
- ; is its length.
- ;
-
- deluel LDY #$00 ; fetch element count
- LDA ($30),Y
- TAX ; transfer length to X
- LDA $2F ; item to delete
- nextel INY ; index to next element
- CMP ($30),Y ; do entry and element match?
- BEQ delete ; yes. delete element
- DEX ; no. decrement element count
- BNE nextel ; any more elements to compare?
- RTS ; no. element not in list. done
-
- ; delete an element by moving the ones below it up one location
-
- delete DEX ; decrement element count
- BEQ deccnt ; end of list?
- INY ; no. move next element up
- LDA ($30),Y
- DEY
- STA ($30),Y
- INY
- JMP delete
- deccnt LDA ($30,X) ; update element count of list
- SBC #$01
- STA ($30,X)
- RTS
-
-
-
-
- ; Example 5-6. 16-bit by 16-bit unsigned multiply
- ;
- ; Multiply $22 (low) and $23 (high) by $20 (low) and
- ; $21 (high) producing a 32-bit result in $24 (low) to $27 (high)
- ;
-
- mlt16 LDA #$00 ; clear p2 and p3 of product
- STA $26
- STA $27
- LDX #$16 ; multiplier bit count = 16
- nxtbt LSR $21 ; shift two-byte multiplier right
- ROR $20
- BCC align ; multiplier = 1?
- LDA $26 ; yes. fetch p2
- CLC
- ADC $22 ; and add m0 to it
- STA $26 ; store new p2
- LDA $27 ; fetch p3
- ADC $23 ; and add m1 to it
- align ROR A ; rotate four-byte product right
- STA $27 ; store new p3
- ROR $26
- ROR $25
- ROR $24
- DEX ; decrement bit count
- BNE nxtbt ; loop until 16 bits are done
- RTS
-
-
-
- ; Example 5-14. Simple 16-bit square root.
- ;
- ; Returns the 8-bit square root in $20 of the
- ; 16-bit number in $20 (low) and $21 (high). The
- ; remainder is in location $21.
-
- sqrt16 LDY #$01 ; lsby of first odd number = 1
- STY $22
- DEY
- STY $23 ; msby of first odd number (sqrt = 0)
- again SEC
- LDA $20 ; save remainder in X register
- TAX ; subtract odd lo from integer lo
- SBC $22
- STA $20
- LDA $21 ; subtract odd hi from integer hi
- SBC $23
- STA $21 ; is subtract result negative?
- BCC nomore ; no. increment square root
- INY
- LDA $22 ; calculate next odd number
- ADC #$01
- STA $22
- BCC again
- INC $23
- JMP again
- nomore STY $20 ; all done, store square root
- STX $21 ; and remainder
- RTS
-
-
- This is based on the observation that the square root of an
- integer is equal to the number of times an increasing odd
- number can be subtracted from the original number and remain
- positive. For example,
-
- 25
- - 1 1
- --
- 24
- - 3 2
- --
- 21
- - 5 3
- --
- 16
- - 7 4
- --
- 9
- - 9 5 = square root of 25
- --
- 0
-
-
- If you are truly interested in learning more, go to your public library
- and seek out an Apple machine language programming book. If your public
- library is like mine, there will still be plenty of early 80s computer
- books on the shelves. :)
-
-