Vocademy |
|
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.
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. |
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
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.
—————————Vocademy |