==================================================================== DR 6502 AER 201S Engineering Design 6502 Execution Simulator ==================================================================== Supplementary Notes By: M.J.Malone Addressing Modes - The Meaning of Arg, Offset and Dest ====================================================== Arg, Offset and Dest are the arguments for various instructions. Since the arguments of instructions are usually referred to by their addresses, the different methods of expressing arguments are called addressing modes. 'Arg' type addressing modes refer to a piece of data usually by its address. The 'Offset' addressing mode is used by branch statements to give a program destination by an offset byte. 'Dest' addressing modes are used to point to a destination in the program. The Use of Labels ================= Assembly code more often uses assembler labels than actual numbers as arguments to increase the readability. In the following example the address of the VIA port, a commonly used memory location, will be assigned a descriptive name to make its later occurrences in assembly code more legible: ; Port_A = $A001 ; Here is another example where a label is assigned the value of a commonly used constant for improved readability: ; MotorBit_Mask = %0000111 ; The use of labels can vastly change the appearance of assembly but does not alter the behavior of addressing modes at all. The Addressing Modes ==================== If there are No Arguments: -------------------------- 0) Implied Some instructions (ie. CLC, SEC, CLD, NOP, BRK, PHA, RTI, RTS etc) do not require arguments. In this case the argument is said to be 'IMPLIED' in the instruction. This is called the implied addressing mode. In Assembly: CLC page 2 'Arg': Refers to a place to find data, usually a memory location ----------------------------------------------------------------- 1) Accumulator The vast majority of statements manipulate data in one way or another and require data for arguments. The first and easiest piece of data to use as an argument is the .A accumulator. Operator instructions such as ROL, ROR, ASL and LSR (and INC and DEC in the 65C02) can use the ACCUMULATOR addressing mode. In Assembly: ROR A 2) Immediate Often a constant (a number) is required in calculations. LDA #$00 takes the number (#) $00 and places it in the accumulator. This is called the IMMEDIATE addressing mode. The following statements can be used with the immediate addressing mode: ADC, AND, CMP, CPX, CPY, EOR, LDA, LDX, LDY, ORA and SBC. In Assembly: ADC #$01 LDA #Constant EOR #Bit_Mask CMP #5 3) Zero Page The memory of the 6502 is divided into $100 (256) pages of $100 (256) bytes each. The pages are numbered from 0 through $FF. Page 0 address are in the range $0000-$00FF. Because 'Zero Page' addresses can be specified in just one byte, instructions using them as arguments can be executed more quickly by the 6502. The statement LDA $80 causes the 6502 to fetch the value from memory location $0080 and place it in the accumulator. Note that the only difference between the immediate and zero page syntax is the # number sign. LDA #$80 means load the number (#) $80 into the accumulator. LDA $80 means load the contents of memory location $0080 into the accumulator. When reading assembly code, the difference is subtle but very important. Zero page addressing can be used with every instruction that uses a data type argument. (This excludes only those that use no argument: CLC, RTI, NOP etc. or a program go to type argument JMP xxxx, JSR xxxx etc.) In Assembly: ADC $80 LDA Temp ( Assuming $00 <= Temp <= $FF ) 4) X and Y Indexed Zero Page Often data is organized into groups of bytes as a table, an array or a record. In this case it is convenient to specify an address as an offset relative to the beginning of the data page 3 structure. The 6502 implements this method using INDEXED addressing. In this case the .X or .Y register is used to add to a zero page address to result in an effective address. IE: LDA $80,X (when .X=#$05) results in a fetch from memory location ($0080+$05)=$0085. This is called the ZERO PAGE X INDEXED addressing mode. The zero page x indexed addressing mode can be used with all instructions except BIT, CPX, CPY, LDX and STX. Note that the .X and .Y registers can take on values of only $00-$FF so the data table is limited in size to $100 bytes. There is also a Y indexed zero page addressing mode but it can be used only with the LDX and STX instructions. This may seem very limiting at first but consider the high level expression: code = Data[ Index_Pointer[i] ]; Where Index_Pointer[] is a small look-up table of pointers to data in the look-up table Data[]. This can be coded easily as: LDY i LDX Index_Pointer,Y LDA Data,X STA code ; 14 machine cycles total Note that indexed zero page addressing cannot result in an effective address outside the zero page. If the sum of the value in the .X register and the base address exceed $FF then the fetch will wrap around to $00 again. For example if the .X register were #$20 then the following memory fetch 'LDA $F0,X' would result in the effective address of ($00F0+$20)=$0110 but the memory fetch would be done on address $0010, still on the zero page. Note that indexed zero page addressing always takes one machine cycle more than non-indexed zero page addressing and hence should be avoided. Often programmers get in the habit of creating small indexed loops to perform operations resulting in a shorter length of assembly code. In the case of mathematics subroutines that manipulate multibyte numbers on the zero page, loops should never be used. The extra overhead required in the INcrement or DEcrement and the Branch instructions as well as the extra machine cycle in each indexed reference can make these routines take almost twice as long to execute as the unravelled equivalent non-indexed routines. 5) Absolute Usually arguments are not stored only on the zero page but come from anywhere in memory. The easiest way to specify a general memory address is to give the full 16 bit address. For example LDA $8000, loads the 8 bit number ($00-$FF) from the memory location $8000. This method of specifying an address is called the ABSOLUTE addressing mode. In Assembly: LDA Port_A ADC $C000 page 4 6) X and Y Indexed Absolute As with zero page addressing, absolute addressing can be indexed as well allowing the entire address space of the 6502 to be used in data tables. The X indexed absolute addressing mode may not be used with: BIT, CPX, CPY, LDX, STX or STY but may be used with LDY. The Y indexed absolute addressing has a similar list except it can be used for LDX and not LDY and cannot be used for the operator instructions ASL, DEC, INC, LSR, ROL or ROR. The absolute X and Y indexed addressing modes require the SAME number of clock cycles to perform as the non-indexed absolute mode. There is therefore NO PENALTY in access time for referring to data as part of a table through indexed addressing in absolute mode. There is of course the INcrement or DEcrement statement, the Branch and possibly the ComParison to create the indexed loop that requires more time over sequential, direct, absolute fetches. The large size of data tables located outside the zero page usually makes sequential absolute fetches impractical since the number of assembly language statements is directly dependent on the size of the table. If the size of the table is variable then indexing must be used. It is often desirable therefore to use indexed absolute addressing and data tables to organize data and reduce the length of the code through indexed loops. There are exceptions to the above statement that indexed and non-indexed absolute addressing require the same number of cycles to execute. The first exception is the use of X indexing with the operator instructions (Y indexing is not available) ASL, DEC, INC, LSR, ROL and ROR. For these instructions, the indexed absolute addressing mode always takes one additional cycle over the regular absolute addressing mode. The second exception has to do with memory pages. For absolute indexed addressing, if the effective address calculation crosses to the next memory page then an additional machine cycle is required for the calculation of the effective address. If the .Y register is #$80 then the memory fetch 'LDA $80C0,Y' crosses from memory page $80 into memory page $81, since the effective address is $8140, and therefore requires an extra machine cycle to perform. It is recommended that data tables be placed entirely on one memory page whenever possible to speed program execution. In Assembly: LDA Game_Board,X STA $1000,Y 7) Indirect The indirect addressing mode is available on the 65C02 only. In this mode a pointer is used to point to an address where the actual data is stored. The 16 bit pointer is stored in two consecutive memory locations on the zero page. The indirect memory fetch 'LDA ($80)' causes the 6502 to look at memory locations $0080 and $0081 to form a 16 bit address. Memory location $0080 is interpreted as the low byte of the address and $0081 as the high byte. If the memory locations $0080 and $0081 hold the values $00 and $20 respectively then the vector ($80) is said to point to address $2000. This method of indirection is standard in high level page 5 languages and is very useful for pointer operations as in the C programming language. The indirect addressing mode is used only for the ADC, AND, CMP, EOR, LDA, ORA, SBC and STA. In Assembly: LDA ($80) STA (Data_Pointer) 8) Indexed Indirect This addressing mode is used for tables of pointers to data. Only the X index register can be used for the indexed indirect addressing mode. In this case the .X register indexes through a data table that is interpreted as 16 bit pointers. If the X register is $04 then the statement: LDA ($80,X) takes value stored in ($0080+$04)=$0084 as the low byte of the 16 bit pointer and the value in $0085 as the high byte of the pointer. If the vector fetch address exceeds $FF then it wraps around to $00 again as in zero page indexed addressing. Note that the X register can only take on meaningful values as an even number since each pointer is two bytes long. One can easily remember how this mode works by remembering that it is called 'Indexed Indirect' where the indexing is done first and then the indirect pointer interpretation is done. Indexed indirect addressing is used only for ADC, AND, CMP, EOR, LDA, ORA, SBC and STA. Page boundaries have no effect on the indexed indirect addressing mode. In Assembly: LDA ($80,X) ADC (Array_of_Pointers,X) 9) Indirectly Indexed This addressing mode is used to index within a data table that is pointed to by a vector on the zero page. Only the Y register can be used for the indirectly indexed address mode. In this case a vector on the zero page points to the first address in a data table and then the Y register indexes through the table. If the Y register is $04 and $0080 and $0081 contain the values $00 and $20 respectively then the instruction 'LDA ($80),Y' first fetches the vector at $0080 and $0081 which points to $2000. The Y register is then added for an effective fetch address of ($2000+$04)=$2004. One can easily remember how this mode works by remembering that it is called 'Indirectly Indexed'. This mode does the indirect pointer interpretation first and then performs the indexing. Indirectly indexed addressing is used only for ADC, AND, CMP, EOR, LDA, ORA, SBC and STA. Page boundaries do effect the indirectly indexed address mode. If the Y index causes the effective address to cross into the next memory page then the fetch requires an additional machine cycle. The indirectly indexed addressing mode is very useful for accessing very large arrays of data. When the size of the array surpasses the $00-$FF limit of the Y index register, the high order byte of the pointer can be incremented to point into the next memory page 6 page. The following is an example of addressing such a large array. ; LDY #$00 Next_Char LDA (String_of_Char),Y ; Get the character from the ; string BEQ End_Of_String ; String ends with a NULL - #$00 JSR Print_Char ; A Subroutine to print ; characters INY ; Go on to next character BNE Next_Char ; If have not finished the page ; - Next INC String_of_Char+1 ; Finished page - Point to next ; page JMP Next_Char ; Go on to first char of next ; page ; ; End_Of_String 'Offset': Branch Destination ----------------------------- 10) Relative The relative addressing mode is used by the Branch statements: BCC, BCS, BEQ, BMI, BNE, BPL, BRA, BVC and BVS. The argument in this case uses one byte as an offset byte. This offset byte allows the branch instruction to branch up to 128 bytes forward and 127 bytes backward in the program machine code. This must seem like a very 'coded', inconvenient, method of doing things. In actuality this is taken care of by the assembler. This is one case where assembler directives are used to make life easy for the programmer. The programmer must however keep in mind that there are limits to the range of relative branches when using them. The following is an example of the assembly code use of a relative branch statement: ; Check_Again LDA Port_A ; Wait for a bit to go high on Port A BEQ Check_Again ; In this example, the assembler records the position of the label 'Check_Again'. When the label is used in the relative branch statement 'BEQ' the ASSEMBLER calculates the required offset byte for the relative addressing mode used for the argument of 'BEQ' instruction. For the user, the only worry is a 'Branch Out of Range Error' at assembly time. If this occurs, then the logic of the branch must page 7 be reversed and a JuMP statement used. For example: ; BEQ Where_to_Go ; <=== This branch is out of range ; becomes: ; BNE Continue_On ; <=== This branch is short - No problem JMP Where_to_Go ; <=== JMP instructions are never out of ; range Continue_On ; The addition of the BRA - branch always statement to the 65C02 is very helpful. If the user knows that the length of a JMP is within range of a branch, it can be converted to a 'BRA Label' instruction saving one machine cycle, critical on maximum repeat rate loops. 'Dest': Jump Destination ------------------------- 11) Absolute This addressing mode is exactly the same in syntax as the absolute addressing mode (see 5 above) except the memory location is not used as a data argument as before but as a memory location at which to find the next instruction operation code. The absolute mode is used by the JMP and JSR instructions and is not influenced by memory pages. Once again as in the relative addressing mode, the ASSEMBLER keeps track of actual addresses within programs and the program merely communicates their desires through the use of labels. In Assembly: JMP Try_Another JSR Print_a_Char JMP $E000 12) Absolute Indirect This addressing mode is used by the JuMP statement to jump to an address pointed to by a vector. The vector, similar to the pointers used in indirect data addressing, is stored as a 16 bit pointer, low byte and high byte. The vector used in absolute indirect addressing may be located anywhere in memory, not necessarily based on the zero page as with indirect data argument addressing. The following is an example: ; JMP ($2000) JMP (Prog_Start_Vector) JMP ($FFFC) ; Simulate a Reset ; Note that the address given in the instructions is an absolute, 16 bit address. page 8 13) Indexed Absolute Indirect This addressing mode is also used by the JuMP statement to jump to an address pointed to by a vector. As in absolute indirect, the vector is stored as a 16 bit pointer, the low byte then the high byte. In indexed absolute indirect addressing, the X register is used to index a table of JuMP vectors in very much the same way as Indexed Indirect (mode 8) data addressing indexes a table of data pointers. Unlike the absolute indirect address mode, the table of jump vectors must be based on the zero page. The following is an example: ; LDX Control_Var JMP (On_Goto_List,X) ; This is an example of using the indexed absolute indirect addressing mode to simulate a BASIC 'ON GOTO' statement, similar to the case and switch statements of structured languages. In Assembly: JMP ($80,X) page 9 Summary Table of Addressing Modes --------------------------------- Type of Addressing Example Comments ===================================================================== Implied CLC What no arguments is called Accumulator ROR A When the .A accumulator is the arg Immediate LDA #$00 When a (#) number is the argument Zero Page LDA $00 When an address <$100 is used Zero Page,X LDA $00,X Indexes a table starting at <$100 Zero Page,Y LDX $00,Y Indexes a table starting at <$100 Absolute LDA $1000 When a general address is used Absolute,X LDA $1000,X Indexes a table anywhere in memory Absolute,Y LDA $1000,Y Indexes a table anywhere in memory *Indirect LDA ($80) Uses $80, $81 as a pointer to arg Indexed Indirect LDA ($80,X) For a table of pointers to arg Indirectly Indexed LDA ($80),Y For a pointer to a table of args Relative BEQ $FE For relative branches Absolute JMP $E000 JMPs to a particular address Absolute Indirect JMP ($0080) Uses $80,$81 as a JMP vector *Indexed Absolute Indirect JMP ($80,X) Uses a table of JMP vectors page 10 Summary of Addressing Mode Restrictions: ---------------------------------------- The instruction classes are listed from the most to the least limiting and the modes available or unavailable to each instruction class. Simply, BIT, TRB and TSB, the bit manipulating instructions are most restrictive. CPx, LDx and STx for the X and Y registers are next most restrictive. The operator instructions ASL, ROR, ROL, LSR, INC and DEC are next most restrictive. The arithmetic and logical instructions: ADC, AND, EOR, ORA, SBC and the accumulator LDA, CMP and STA are least restrictive. Instructions 6502 65C02 ==================================================================== BIT Zero Page and Added: Immediate, and X indexed Absolute only Zero Page and Absolute TRB, TSB Zero Page and Absolute only CPX, CPY Immediate, Zero Page and Absolute only STX Zero Page,Y \ Zero Page and Absolute STY Zero Page,X / STZ Absolute, Zero Page and X indexed Absolute and Zero Page LDX Y indexed Zero Page and Absolute \ and: LDY X indexed Zero Page and Absolute / Immediate, Zero Page and Absolute ASL, LSR, Accumulator, Zero Page, ROR, ROL Absolute, X indexed Zero Page and Absolute page 11 DEC, INC, Zero Page, Absolute and Added: Accumulator X indexed Zero Page and Absolute STA All except Immediate and: Added: Indirect ADC, AND, CMP, All except Accumulator EOR, LDA, ORA, and Zero Page,Y SBC