At their core, all general purpose computers work in the same underlying fashion; data stored in a
main memory is read by the
central processing unit (CPU) into a fast temporary memory (such as a set of
CPU registers), acted on, and then written back to main memory. Memory consists of a collection of data values, encoded as numbers and referred to by their
addresses, each also a numerical value. This means the same operations applied to the data can be applied to the addresses themselves. While being worked on, data can be temporarily held in
processor registers, scratchpad values that can be accessed very quickly. Registers are used, for example, when adding up strings of numbers into a total.
Single instruction, single operand In early computers, the
instruction set architecture (ISA) often used a single register, in which case it was known as the
accumulator. Instructions included an address for the operand. For instance, an ADD
address instruction would cause the CPU to retrieve the number in memory found at that address and then add it to the value already in the accumulator. This very simple example ISA has a "one-address format" because each instruction includes the address of the data. One-address machines have the disadvantage that even simple actions like an addition require multiple instructions, each of which takes up scarce memory, and requires time to be read. Consider the simple task of adding two numbers in memory, 5 and 4. In this case, the program would have to load the value 5 from memory into the accumulator with the LOAD
address instruction, use the ADD
address instruction pointing to the 4, and finally SAVE
address to store the result, 9, back to another memory location.
Single instruction, multiple operands Further improvements can be found by providing the address of both of the operands in a single instruction, for instance, ADD
address 1,
address 2. Such "two-address format" ISAs are very common. One can further extend the concept to a "three-address format" where the SAVE is also folded into an expanded ADD
address 1,
address 2,
address of result. It is often the case that the basic
computer word is much larger than needed to hold just the instruction and an address, and in most systems, there are leftover bits that can be used to hold a constant instead of an address. Instructions can be further improved if they allow any one of the operands to be replaced by a constant. For instance, ADD
address 1,
constant 1 eliminates one memory cycle, and ADD
constant 1,
constant 2 another.
Multiple data Complexity arises when one considers common patterns in which memory is accessed. One very common pattern is that a single operation may be applied across a large amount of similar data. For instance, one might want to add up 1,000 numbers. In a simple two-address format of instructions, there is no way to change the address, so 1,000 additions have to be written in the
machine language. ISAs fix this problem with the concept of
indirect addressing, in which the address of the next point of data is not a constant, but itself held in memory or a machine register. This means the programmer can change the address by performing addition on that memory location or register. ISAs also often include the ability to offset an address from an initial location, by adding a value held in one of its registers, in some cases a special
index register. Others carry out this addition automatically as part of the instructions that use it. The variety of
addressing modes leads to a profusion of slightly different instructions. Considering a one-address ISA, for even a single instruction, ADD, we now have many possible "addressing modes": • Immediate (constant): ADD.C
constant 1 — adds the constant value to the result in the accumulator • Direct address: ADD.A
address 1 — add the value stored at address 1 • Memory indirect: ADD.M
address 1 — read the value in address 1, use that value as another address and add that value Many ISAs also have registers that can be used for addressing as well as math tasks. This can be used in a one-address format if a single address register is used. In this case, a number of new modes become available: • Register direct: ADD.R
register 1 — add the value stored in the address held in register one • Displacement: ADD.D
constant 1 — add the constant to the address register, then add the value found in memory at that resulting location • Index: ADD.I
register 1 — add the value in register 1 to the address register to make a new address and then adds the value at that location to the accumulator • Autoindex: ADD.AI
register 1 — as in the Index case, but automatically increments the address ==Orthogonality==