## Basic Components

This is going to be really simple. Our computer will have:
• A 32-bit register, called the accumulator ($A$).
• A 32-bit register, called the instruction pointer ($IP$).
• 256 million+ words of memory (i.e., $2^{28} = 268435456$ words), each 32-bits wide. The first word of memory we denote by $M[0]$, the second by $M[1]$, the third by $M[2]$, and so on...
• Up to 256 million+ (again, $2^{28}$) ports. Similar to the notation used for memory, the first port is $P[0]$, the second is $P[1]$, the third is $P[2]$, and so on...

## Operation

At each “step”, the computer reads the memory word whose address is in $IP$ and then increments $IP$. Then it carries out the instruction that that word represents.

This is how most computers, uh, cores, work. It is called the fetch-execute cycle.

## The Instructions

Each word that the computer tries to execute will be interpreted to have:

• The first 4 bits (i.e., enough bits to specify one hexadecimal digit) as the opcode.
• The remaining 28 bits (which can be specified by 7 hexadecimal digits) will refer to a memory address or port number.

For a given instruction word, let’s denote by $op$ the hexadecimal digit corresponding to the first four bits, and let $x$ represent the last 28 bits. With these, we formally specify the operation of each instruction as follows.

(Note, "$:=$" is used to represent the "assignment" of the value to the right of this symbol to the element on its left.)

opMnemonicActionRemarks
0LOAD$A := M[x]$Load accumulator from memory
1STORE$M[x] := A$Store accumulator to memory
2IN$A := P[x]$Read from a port into the accumulator
3OUT$P[x] := A$Write accumulator out to a port
4ADD$A := A + M[x]$Add into accumulator
5SUB$A := A - M[x]$Subtract from accumulator
6MUL$A := A \times M[x]$Multiply into accumulator
7DIV$A := A \div M[x]$Divide accumulator
8MOD$A := A \:\texttt{mod}\: M[x]$Modulo
9AND$A := A \,\&\, M[x]$Bitwise AND
AOR$A := A \,\,|\,\, M[x]$Bitwise OR
BXOR$A := A \wedge M[x]$Bitwise XOR
CJUMP$IP := x$Jump to new address
DJZif $A = 0$ then $IP := x$Jump if accumulator is zero
EJLZif $A < 0$ then $IP := x$Jump if accumulator is less than zero
FJGZif $A > 0$ then $IP := x$Jump if accumulator is greater than zero

## An Example Program

This program, when loaded into memory at address 0, outputs powers of two, starting with 1, and going just past 1,000,000, to port 100 (64 hex):

C0000003
00000001
000F4240
00000001
30000064
40000001
10000001
50000002
E0000003
C0000009


## Assembly Language

The example above was hard to read. Just listing the contents of memory that the processor executes is called “writing machine language.” Let’s use the mnemonics given in the above table for each instruction to make things a bit clearer. Then the example becomes:

 0000 0001 0002 0003 0004 0005 0006 0007 0008 0009  C0000003 00000001 000F4240 00000001 30000064 40000001 10000001 50000002 E0000003 C0000009   JUMP start ; begin by jumping over the data area pow: 1 ; store the current power value here limit: 1000000 ; we'll be computing powers up to this amount start: LOAD pow ; bring the value into accumulator to use OUT 100 ; output the current power ADD pow ; adding to itself makes the next power! STORE pow ; store it (for next time) SUB limit ; we need to compare with limit, subtracting helps JLZ start ; if not yet past limit, keep going end: JUMP end ; this "stops" the program! 

In general, each line of an assembly language program contains:

• An optional label (so you don't have to memorize physical addresses)
• Either
• A data value
• An instruction and its operands. An operand can be a direct value or a label. (Labels are just convenient shorthands for values anyway.)
• Comments, beginning with the ; character.

The process of converting from assembly language to machine language is called assembly. The reverse process is called disassembly. Yes, there exist programs called assemblers and disassemblers.

Original text by Ray Toal of Loyola Marymount University; adapted by P. Oser