6809 ASSEMBLY LANGUAGE PROGRAMMING Why should I learn assembly language programming? BASIC should be good enough for most things you wand to do with your computer, but what if BASIC is too slow for some task or other? Assembly language is much faster that BASIC because it goes right to the computer instead of having to be interpreted first. How hard is it to learn? It does not have to be diff- icult to learn if it is presented in manageable chunks. It may get frustrating at times when you just don't understand something, but with patience, you can prevail. What do I need to begin? An editor/assemble would be handy, though not necessary. All the programs presented here will be compatible with EDTASM+ but I will also explain how to assemble code (along with defining what assembly is!). When do we begin? We can begin right away. Don't get too rambuctious yet; there is some boring details to go through before we can do any programming. THE ASSEMBLY LANGUAGE LISTING: 7F00 ORG $7F00 START AT $7F00 7F00 8E 0400 CLRSCN LDX #$400 GET START OF SCREEN 7F03 86 60 LDA #$60 GET SPACE CHARACTER 7F05 A7 80 LOOP STA ,X+ STORE SPACE 7F07 8C 05FF CMPX #$5FF ARE WE DONE YET? 7F0A 23 F8 BLS LOOP CONTINUE IF NOT 7F0C 39 RTS RETURN ````````````````` `````` ````````````````````````` MACHINE CODE SYMBOL ASSEMBLY CODE Do not worry about the funny symbols yet. The convention when programming in assembly language is to use hexadecimal (base 16) preceded by a $. A machine code listing, on the other hand, uses hexadecimal without any marker. The difference is that with assembly language we are permitted to use decimal numbers (no prefix) as well as hexadecimal. Usually, symbols are used to mark locations call via jump instructions (much like BASIC line numbers). Most times, a listing will appear like the one above. The first column under machine code is the address, the rest of the numbers are the machince code itself. Next will be the assembly code, usually with a line number (not shown) in which the first column is the symbol, the next is the assembly instruction, and finally any comments. A comment line may be instseted be preceding it with a *. ADDRESSING MODES: There are several different types of instructions. There are instructions which use registers only, some which access memory, and some which do nothing or jump somewhere else (like GOTO or GOSUB). Inherent addressing: this involves implied addressing. The location being addressed (usually a register) is contained in the instruction. ex: ABX, NEGA, NOP Register addressing: this involves a byte which is interpreted depending on the instruction. Ex: EXG, PSHS Indexed addressing: this involves using the X or Y index registers, or the S or U stacks to refer to the location which is being accessed. Direct addressing: this accesses a memory location directly. It can either be 1 byte (direct page) or 2 bytes (extended). Direct page addressing is preceded by a < while extended addressing is preceded by a >. Indirect addressing: this accesses a memory location indirectly via another memory location. A location can be addressed indirectly via extended or indexed addressing. Relative addressing: this is relative to the present location. Many branch instructions use this mode and others can access it as PROGRAM COUNTER RELATIVE. Program counter relative can also be indirect. Immediate addressing: the values used by this addressing mode are contained directly in the machine code itself. PSEUDO INSTRUCTIONS: There are several instructions which can appear in an assembly language listing which are not microprocessor instructions. These are called PSEUDO OPS which are used to direct the assembly process. These are: ORG: sets the current location of assembly EQU: sets the location of a symbol not defined elsewhere SET: sets a variable location on a symbol FCB: forms a 1 byte constant data value FDB: forms a 2 byte constant data value FCC: forms a constant string of characters END: used to mark the end of assembly REGISTERS: I have mantioned registers before. They are locations in the microprocessor which are used to store temporary data. Here is a list of 6809 registers: A,B - single byte accumulators. They are used for single byte arithmetic instructions. D - this is a double accumulator with A and B teaming up to hold its results. It can only be added to, subtracted from, and compared. X,Y - two byte index registers. They are used to point to tables, etc. S - hardware stack. JSR, BSR, LBSR (like GOSUB), PSHS, PULS, RTS (RETURN), RTI (RETURN from interrupt) use this. U - user stack. PSHU, PULU use this register. It is more commonly used as an index register. The S can be used as well as an index register. PC - program counter. This register keeps a running count of the current location the computer is executing. DP - direct page. This is used as the 1st byte of a 2 byte address in the direct page addressing mode. CC - condition codes. This is not really a register but a collection of flags which explain the current state of the microprocessor. INSTRUCTIONS: All instructions consist of a one or two byte operation code and a zero to three byte operand. The operation code is the machine code for the assembly language instruction while the operand is a code for the assembly language operand. The following should clarify the point some: 00010 START LDA #$60 COMMENTS ` ` ` ` ` ` ` operand (immediate addressing preceded ` ` ` by a #) ` ` operation code (opcode for short) ` symbol line number The machine code for the above instruction is as follows: opcode: $86 operand: $60 There are several instructions which do not use registers at all: NOP - no operation - $12 SYNC - synchronize with interupt - $13 SWI - execute software interupt - $3F SWI2 - ececute software interupt 2 - $103F SWI3 - ececute software interupt 3 - $113F RTS - return from subroutine - $39 RTI - return from interupt - $3B There are several arithmetic functions which may use direct page, extended, or indexed addressing. These are listed with opcodes in order or direct page, extended, indexed. NEG - negate - $00, $70, $60 COM - complement - $03, $73, $63 LSR - logical shift right - $04, $74, $64 ROR - rotate right - $06, $76, $66 ASR - arithmetic shift right - $07, $77, $67 ASL - arithmetic shift left - $08, $78, $68 LSL - logical shift left - $08, $78, $68 ROL - rotate left - $09, $79, $69 DEC - decrement - $0A, $7A, $6A INC - increment - $0C, $7C, $6C CLR - clear - $0F, $7F, $6F The above instructions may be done on both accumulators also: Instr. A/B NEGA/B $40/$50 COMA/B $43/$53 LSRA/B $44/$54 RORA/B $46/$56 ASRA/B $47/$57 ASLA/B $48/$58 LSLA/B $48/$58 ROLA/B $49/$59 DECA/B $4A/$5B INCA/B $4C/$5C CLRA/B $4F/$5F There are several branch instructions which use relative addressing. The fist code refers to the instruction without the L in front. The second refers to the instruction with the L in front (read as LONG ... with the L in front) L/BSR - branch to subroutine - $8D/$17 L/BRA - branch always - $20/$16 L/BRN - branch never - $21/$1021 -- NOP instruction! L/BHI - branch if higher - $22/$1022 L/BLS - branch if lower or same - $23/$1023 L/BCC - branch if carry clear - $24/$1024 L/BHS - branch if higher or same - $24/$1024 L/BCS - branch if carry clear - $25/$1025 L/BLO - branch if lower - $25/$1025 L/BNE - branch if not equal - $26/$1026 L/BEQ - branch if equal - $27/$1027 L/BVC - branch if overflow clear - $28/$1028 L/BVS - branch if overflow set - $29/$1029 L/BPL - branch if plus - $2A/$102A L/BMI - branch if minus - $2B/$102B L/BGE - branch if greater or equal - $2C/$102C L/BLT - branch if less than - $2D/$102D L/BGT - branch if greater than - $2E/$102E L/BLE - branch if less or equal - $2F/$102F The rest of the jump instructions are listed below in the same format as the arithmetic functions. JSR - jump to subroutine - $9D, $BD, $AD JMP - jump - $0E, $7E, $6E The following are the misclaneous instructions that are cluttering the house. DAA - decimal adjust A - $19 ORCC - Logical or on CC (immediate only) - $1A ANDCC - Logical and on CC (immediate only) - $1C SEX - sign extend B into A - $1D EXG - exchange registers (register) - $1E TFR - transfer register to another (reg.) - $1F ABX - add B to X unsigned - $3A CWAI - clear and wait for interupt (imm.) - $3C MUL - multiply accumulators unsigned - $3D LEAX - load effective address to X (indexed) - $30 LEAY - load effective address to Y (indexed) - $31 LEAU - load effective address to U (indexed) - $33 LEAS - load effective address to S (indexed) - $32 PSHS - push to hardware stack (register) - $34 PULS - pull from hardware stack (register) - $35 PSHU - push to user stack (register) - $36 PULU - pull from user stack (register) - $37 The following are instructions for A. Add $40 for the same instruction for B. The first code is immediate, the second, direct page, the third, extended, and the fourth, indexed. SUBA - subtract from A - $80, $90, $B0, $A0 CMPA - compare A - $81, $91, $B1, $A1 SBCA - subtract from A with borrow - $82, $92, $B2, $A2 ANDA - logical and A - $84, $94, $B4, $A4 BITA - bit test A - $85, $95, $B5, $A5 LDA - load A - $86, $96, $B6, $A6 STA - store A - XX, $97, $B7, $A7 EORA - logical xclusive or A - $88, $98, $B8, $A8 ADCA - add to A with carry - $89, $99, $B9, $A9 ORA - logical or A - $8A, $9A, $BA, $AA ADDA - add to A - $8B, $9B, $BB, $AB The following are the accumulator D instructions: LDD - load D - $CC, $DC, $FC, $EC STD - store D - XX, $DD, $FD, $ED ADDD - add to D - $C3, $D3, $F3, $E3 SUBD - subtract from D - $83, $93, $B3, $A3 CMPD - compare D - $1083, $1093, $10B3, $10A3 The following are the index X instructions. Add $10 in front for the corresponding Y instructions. LDX - load index X - $8E, $9E, $BE, $AE STX - store index X - XX, $9F, $BF, $AF CMPX - compare X - $8C, $9C, $BC, $AC These are the instructions for the S and U registers: LDU - load U - $CE, $DE, $FE, $EE STU - store U - XX, $DF, $FF, $EF CMPU - compare U - $1183, $1193, $11B3, $11A3 LDS - load S - $10CE, $10DE, $10FE, $10EE STS - store S - XXXX, $10DF, $10FF, $10EF CMPS - compare S - $118C, $119C, $11BC, $11AC INDEXED ADDRESSING: One last thing before I close this article. Indexed addressing bears some discussion since it is so complicated and vital to assembly language programming. The following table gives the binary breakdown of the byte following the opcode (post byte) for each individual indexing operation. Type Form Assm Form direct Offset from R No offset ,R 1RR00100 5-bit n,R 0RRnnnnn 8-bit nn,R 1RR01000 16-bit mmnn,R 1RR01001 Accumulator A A,R 1RR00110 offset from R B B,R 1RR00101 D D,R 1RR01011 Auto Increment/ +1 ,R+ 1RR00000 decrement +2 ,R++ 1RR00001 -1 ,-R 1RR00010 -2 ,--R 1RR00011 Program Counter 8-bit nn,PCR 1XX11100 relative 16-bit mmnn,PCR 1XX11101 Extended indirect [mmnn] 1XX11111 RR:00=X, 01=Y, 10=U, 11=S R=X,Y,U, or S XX= doesn't matter Note: to acheive indirect addressing for above, add [] around the assembler form and change the bit after RR or XX to a 1. 5-bit offset from R and auto increment/decrement by one are not available in indirect. NEXT MONTH: We will start with a simple programming project next month. I suggest that you print out this article and keep a copy on hand for next month. I will be assuming that you have a hardcopy of the information presented here. See you next month; It won't be quite as long, I hope!