Vocademy

Programming the 6502

Assembly language

6502 Programmers Model

So far, we have seen programming in the native language of a microprocessor. This is called machine language and is different for each microprocessor family. Programming in machine language is quite tedious. For example, the 6502 has eight addressing modes. Each instruction has a separate op-code for each addressing mode available to it. Therefore, there are eight different op-codes for the instruction to copy data to the accumulator. There are also eight other op-codes to add data to the data already stored in the accumulator. There are 63 different op-codes for the eight basic microprocessor operations.[1]

To make programming easier, programs called assemblers are available. Assemblers facilitate a more human-friendly language called assembly language. Assembly language uses mnemonics[2] that translate directly into op-codes for the processor. There are also standard ways to specify each addressing mode. Combining these makes an easier-to-remember language. For example, the previous three instructions in 6502 assembly language looks like:

LDA #$0A ;Load accumulator immediate (op-code: A9)
LDA $8BCD ;load accumulator absolute (op-code: AD)
LDA $8BCD,X ;load accumulator absolute, indexed by X (op- code: BD)

The assembly language for the add instruction, using the same three addressing modes, looks like:

ADC #$0A ;add to accumulator immediate (op-code: 69)
ADC $8BCD ;add to accumulator absolute (op-code: 6D)
ADC $8BCD,X ;add to accumulator absolute, indexed by X (op-code: 7D)

Assembly language translates directly to machine language, so it loses none of the efficiency of working with machine language. However, it relieves much of the tedium by isolating the programmer from the numeric op-codes. For the eight basic operations, there are eight mnemonics. Then, there are eight syntaxes[3] for each of the eight addressing modes. The mnemonics are easy to remember, such as LDA for "load the accumulator" and ADC for "add to the accumulator." For the eight basic operations, the programmer must only remember eight mnemonics and eight addressing mode syntaxes—a total of 16 items rather than 63 op-codes. There are 64 operations with the 6502, several with multiple addressing modes, for 160 numerical op-codes. Assembly language reduces this to 64 mnemonics and eight addressing mode syntaxes.

Assembly language syntax

The 6502 assembly language mnemonics for the nine fundamental operations are:

LDA
STA
ADC
SBC
AND
 Load Accumulator
Store Accumulator
ADD to Accumulator
Subtract from Accumulator[4]
Boolean AND
ORA
EOR
CMP
BNE
Boolean OR
Boolean Exclusive OR
CMP Compare
BNE Branch if Not Equal

Some other basic operations are:

INX  Increment the X register RTI Return from interrupt
INY Increment the Y register BEQ Branch if equal
INC Increment memory BMI Branch if minus
ASL Shift all bits left BPL Branch if plus
LSR Shift all bits right BCS Branch if the carry flag is set
JMP Jump BCC Branch if the carry flag is clear
JSR Jump to subroutine BVS Branch if the overflow flag is set
RTS Return from subroutine BVC Branch if the overflow flag is clear

There are also several operations that move data between registers and manage status indicators, such as:

TAX Transfer the accumulator to X SEC Set the carry flag
TAY Transfer the accumulator to Y CLC Clear the carry flag
TXA ADD to Accumulator CLV Clear the overflow flag
TYA Transfer Y to the accumulator    

These are about half of the available operations for the 6502.

To specify an instruction in assembly language, the mnemonic is listed, followed by any data to be operated on (immediate mode) or an address of data to be operated on (absolute or indirect modes). For example, the assembly language instruction to load the accumulator with the decimal number 12 is:

 LDA #$0C

With this instruction, the pound sign (#) specifies the immediate addressing mode. The dollar sign ($) specifies that the following data is represented by a hexadecimal number. The same instruction specifying the data as a decimal number would be:

LDA #12

To specify the absolute addressing mode, the mnemonic is followed by a 16 bit number specifying the address of the data to be operated on. For example, the following will load the accumulator with the byte of data stored at 8BDC (35,789 decimal);

LDA $8BCD

Absolute, indexed addressing is specified by listing the register to index by, following a comma. For example, to load the accumulator using the absolute, indexed addressing mode would use instruction like:

LDA $8BCD,X LDA $8BCD,Y

The other addressing modes are, using the LDA command as an example:

LDA $20 Zero-page absolute – This is like the absolute mode except the address is specified with an eight bit number instead of a 16 bit number. Since an eight bit number can only specify decimal numbers from 0 to 255, the address has to be in the first 256 bytes of memory. The first 256 bytes of memory are called the zero page.
 
LDA $20,X Zero page absolute, indexed by X.
 
LDA $20,Y Zero page absolute, indexed by Y.
 
LDA ($8BCD,X) Indirect, pre-indexed by X – This is the same as absolute, indexed by X except the specified address doesn't contain the data to be operated on. The address is the first byte of another 16 bit address that is where the data is actually located.
 
LDA ($8BCD),Y Indirect, post-indexed by Y – Same as absolute except the address doesn't contain data to be operated on. It contains another 16 bit address, indexed by Y, where the data actually is.
 

Why indirect addressing

Operating systems are made up of many small programs called service routines. These service routines wait in memory until called upon by an interrupt[5]. For example, when you press a key on your keyboard, the interrupt pin on the microprocessor receives a signal. The microprocessor stops what it is doing and jumps to the keyboard service routine[6]32. The microprocessor does what it needs to do to process the keyboard information then goes back to what it was doing when it received the interrupt signal.

Operating systems use indirect addressing modes to facilitate a directory that lists where the service routines are stored in memory. This is like a building directory. For example, to get to a certain business' office, you look them up in the directory, which in turn gives you the suite number to go to. The directory in the computer is called the interrupt vector table. It is a list of the addresses of all the interrupt service routines. When a service routine is needed, the microprocessor uses indirect addressing to look up the location of the service routine and then jump to it.

Programs should never go directly to the service routines. If the location of a service routine changes, as it is likely to do when a an operating system is upgraded, programs that bypass the directory will not be able to find the routines. In the building directory example, if a business moves to another suite in the building, and a customer ignores the change in the building directory, they will end up at the wrong suite. A person can just excuse himself and look up the new suite in the building directory. An application program will likely just crash. As long as the vector table is properly updated when there is an operating system upgrade, programs will always be able to find the service routines.

Other uses of this technique will be discussed later with operating systems

Stack overflow

A stack overflow occurs when too many bytes are placed on the stack. This will activate the stack overflow indicator in the status register (the stack overflow flag) and usually generates an error that halts the offending program (a fatal error). A stack overflow can also cause data to be written to memory that is not part of the memory reserved for the stack. Malicious programmers can exploit this to compromise a computer.

—————————
1the 'copy data in the accumulator to memory' command doesn't have an immediate mode. Otherwise, there would be 64 basic op-codes.
2A mnemonic is a memory aid. In assembly language short codes like LDA are easier to remember than binary codes.
3Syntax is the set of rules to construct a statement.
4The 6502 has no complement command. It has a subtract command instead.
5An interrupt will cause the microprocessor to stop what it is doing and switch temporarily to another task. Interrupts will be discussed in detail later.
6How it knows that it was the keyboard that caused the interrupt will be discussed later.
Vocademy