Imagine a bookshelf divided into 100 small cubbyholes, each identified with a number. Starting from number 1 in the upper lefthand corner, the first row has compartments 1, 2, 3, 4, 5, 6, 7, 8, 9, and 10. The next row continues with 11, 12, and so on. In each compartment, we can put a piece of paper with a number or an instruction. Now, let us set up the compartments as follows:
Cell number | Contents |
---|---|
1 | Take next instruction from cell 21 |
2 | 6 |
3 | 21 |
4 | 46 |
5 | 396 |
6 | 134 |
7 | 58 |
8 | 93 |
9 | 0 |
10 | 0 |
11 | 0 |
12 | 0 |
13 | 0 |
14 | 0 |
15 | 0 |
16 | 0 |
17 | 0 |
18 | 0 |
19 | 0 |
20 | 0 |
21 | Copy the number in cell 2 to cell 20 |
22 | Put Zero in cell 19 |
23 | Put 3 in cell 18 |
24 | Using cell 18 as the number of a cell, add the number in that cell to cell 19. |
25 | Add 1 to the number in cell 18 |
26 | Subtract 1 from the number in cell 20 |
27 | If cell 20 is not zero, take next instruction from cell 24 |
28 | Copy the number in cell 19 to cell 17 |
29 | Divide the number in cell 17 by the number in cell 2 |
30 | STOP |
(Answer: The program can work on no more than 15 numbers.)
Well, the computer you are using at school is a little more user- friendly than this, but basically, that is what it does.
The model A computer has 1000 data/program cells, numbered from 1 to 1000.
Each cell can hold a number with up to 6 digits.
Programs always start executing instructions in cell 1.
Each instruction can mention up to 2 addresses, numbers of cells used as data in computation. Programs consist of the following instructions:
JUMP cell1 | Take next instruction from cell1 |
JUMP (cell1) | Take next instruction from the cell with the number indicated by the number in cell1. |
MOVE cell1, cell2 | Copy a data value from one cell to another. After the operation, cell1 is unchanged. |
MOVE #number, cell2 | Put a value (a small integer value) into the cell mentioned. |
MOVE (cell1), cell2 | Using the number in cell1 as a pointer to a cell, put the contents of that cell into cell2. Only cell2 is changed |
ADD cell1, cell2 | Add the number in cell1 to the number in cell2, leaving the result in cell2. |
ADD #number, cell2 | Add a small number to cell2. |
ADD (cell1), cell2 | Using the number in cell1 as a pointer to a cell, add the contents of that cell to cell2, leaving the result in cell2. |
SUB cell1, cell2 | Subtract the number in cell1 from the number in cell2, leaving the result in cell2. |
SUB #number, cell2 | Subtract a small number from cell2. |
SUB (cell1), cell2 | Using the number in cell1 as a pointer to a cell, subtract the contents of that cell from cell2, leaving the result in cell2. |
MUL cell1, cell2 | Multiply the number in cell2 by the number in cell1, leaving the result in cell2. |
MUL #number, cell2 | Multiply call2 by a small number. |
MUL (cell1), cell2 | Using the number in cell1 as a pointer to a cell, multiply cell2 by the contents of that cell, leaving the result in cell2. |
DIV cell1, cell2 | Divide the number in cell2 by the number in cell1, leaving the result in cell2. |
DIV #number, cell2 | Divide a small number into cell2. |
DIV (cell1), cell2 | Using the number in cell1 as a pointer to a cell, divide the contents of that cell into cell2, leaving the result in cell2. |
JZERO cell1, cell2 | If cell1 is zero, jump to cell2, otherwise continue with the next instruction |
JZERO (cell1), cell2 | If the cell pointed to by cell1 is zero, jump to cell2, otherwise continue with the next instruction |
JNZERO cell1, cell2 | If cell1 is not zero, jump to cell2, otherwise continue with the next instruction |
JNZERO (cell1), cell2 | If the cell pointed to by cell1 is not zero, jump to cell2, otherwise continue with the next instruction |
JNEG cell1, cell2 | If cell1 is less than zero, jump to cell2, otherwise continue with the next instruction |
JNEG (cell1), cell2 | If the cell pointed to by cell1 is less than zero, jump to cell2, otherwise continue with the next instruction |
STOP | Program is complete |
In addition, the following commands can be used to stuff data into cells before the program starts: | |
DATA value | The cell contains the indicated number |
TEXT "abcd" | The cell contains the indicated 4 letters as data |
We can now write the program from before in the concise form:
Cell number | Contents |
---|---|
1 | JUMP 21 |
2 | DATA 6 |
3 | DATA 21 |
4 | DATA 46 |
5 | DATA 396 |
6 | DATA 134 |
7 | DATA 58 |
8 | DATA 93 |
9 | DATA 0 |
10 | DATA 0 |
11 | DATA 0 |
12 | DATA 0 |
13 | DATA 0 |
14 | DATA 0 |
15 | DATA 0 |
16 | DATA 0 |
17 | DATA 0 |
18 | DATA 0 |
19 | DATA 0 |
20 | DATA 0 |
21 | MOVE 2,20 |
22 | MOVE #0,19 |
23 | MOVE #3,18 |
24 | ADD (3),19 |
25 | ADD #1,18 |
26 | SUB #1,20 |
27 | JNZERO 20,24 |
28 | MOV 19,17 |
29 | DIV 2,17 |
30 | STOP |
All practical computers today use binary numbers inside. In school, we call this base-2 numbers, as opposed to our everyday base-10 numbers. Some early computers used a form of base-10 numbers known as BCD (Binary Coded Decimal). But often, we find that binary numbers are too cumbersome to write (too many digits) and for convenience they may be written in base-8 (octal) or base-16 (hexadecimal or hex). Here is a handy comparison table:
Decimal | Binary | Octal | Hex |
---|---|---|---|
0 | 0000 0000 0000 | 0000 | 000 |
1 | 0000 0000 0001 | 0001 | 001 |
2 | 0000 0000 0010 | 0002 | 002 |
3 | 0000 0000 0011 | 0003 | 003 |
4 | 0000 0000 0100 | 0004 | 004 |
5 | 0000 0000 0101 | 0005 | 005 |
6 | 0000 0000 0110 | 0006 | 006 |
7 | 0000 0000 0111 | 0007 | 007 |
8 | 0000 0000 1000 | 0010 | 008 |
9 | 0000 0000 1001 | 0011 | 009 |
10 | 0000 0000 1010 | 0012 | 00A |
11 | 0000 0000 1011 | 0013 | 00B |
12 | 0000 0000 1100 | 0014 | 00C |
13 | 0000 0000 1101 | 0015 | 00D |
14 | 0000 0000 1110 | 0016 | 00E |
15 | 0000 0000 1111 | 0017 | 00F |
16 | 0000 0000 1000 | 0020 | 010 |
17 | 0000 0000 1001 | 0021 | 011 |
... | ... | ... | ... |
64 | 0000 0100 0000 | 0100 | 040 |
... | ... | ... | ... |
1023 | 0011 1111 1111 | 1777 | 3FF |
... | ... | ... | ... |
4095 | 1111 1111 1111 | 7777 | FFF |
This table shows how numbers were stored in a machine where each cell can hold 12 binary digits, or 12 bits. As you can see, this allows us to store numbers up to 4096. There have been some machines that used 12 bits as their word size, most famously the PDP-8 minicomputer from Digital Equipment corporation, the first computer that could be sold for less than $10,000. We said above, that the model A can store 6-digit numbers, so it must use more than 12 bits; in fact it would probably be a 24-bit machine. But we could do all the same things with a 12-bit machine; we would just say that it takes 2 cells to store a number. There is another reason that I propose a larger word size: The instructions have to fit in a cell, and many of the instructions need to be able to contain the addresses of two cells. Since I said that the model A has 1000 cells, we need at least 10 bits for an address. If the MOVE instruction was the only one allowed to have two addresses, that would make 24 bits the smallest practical word size. But with the instruction set outlined above, we need to be able to hold
One more thing about numbers to think about: We need to be able to accomodate negative numbers. We also want to be able to accommodate numbers that are not whole numbers. And we need to have a way to catch the situation when a multiplication produces numbers that don't fit in a cell (because they are too large).
Negative numbers are simple: The highest digit is reserved to say "this is a negative number". Then we just continue counting down past 0.
Decimal | Binary | Octal | Hex |
---|---|---|---|
2047 | 0111 1111 1111 | 3777 | 7FF |
1023 | 0011 1111 1111 | 1777 | 3FF |
... | ... | ... | ... |
64 | 0000 0100 0000 | 0100 | 040 |
... | ... | ... | ... |
1 | 0000 0000 0001 | 0001 | 001 |
0 | 0000 0000 0000 | 0000 | 000 |
-1 | 1111 1111 1111 | 7777 | FFF |
-2048 | 1000 0000 0000 | 4000 | 800 |
Working on non-whole numbers is harder. In fact, very small and inexpensive computers (like the one that controls your microwave oven or the engine in your car) do not have instructions and circuits to do it. Larger computers use a representation called floating point to hold numbers of a greater range with less precision. (You will eventually get bored with this detail; when you do, skip forward to Input and Output.) In the model A computer, this works as follows:
The data cell is divided in three parts:
Sign Bit | As with whole numbers, the top bit indicates whether this is a positive or a negative number. |
Exponent | The next 7 bits indicate roughly how large the number is. This is a scale factor from -63 to +63 indicating a power of two that the mantissa must be multiplied by in order to get the real number. The exponent value of -64 is reserved to say that the number is invalid. All operations that fail because they deliver numbers outside of the usable range will return a value with the illegal exponent to prevent continuing the calculation with wrong values. |
Mantissa | The actual value (to be scaled according to the exponent part. Since we took away 8 bits for sign and exponent, we are left with about 9 digits of precision. |
FADD cell1, cell2 | Add the number in cell1 to the number in cell2, leaving the result in cell2. |
FADD (cell1), cell2 | Using the number in cell1 as a pointer to a cell, add the contents of that cell to cell2, leaving the result in cell2. |
FSUB cell1, cell2 | Subtract the number in cell1 from the number in cell2, leaving the result in cell2. |
FSUB (cell1), cell2 | Using the number in cell1 as a pointer to a cell, subtract the contents of that cell from cell2, leaving the result in cell2. |
FMUL cell1, cell2 | Multiply the number in cell2 by the number in cell1, leaving the result in cell2. |
FMUL (cell1), cell2 | Using the number in cell1 as a pointer to a cell, multiply cell2 by the contents of that cell, leaving the result in cell2. |
FDIV cell1, cell2 | Divide the number in cell2 by the number in cell1, leaving the result in cell2. |
FDIV (cell1), cell2 | Using the number in cell1 as a pointer to a cell, divide the contents of that cell into cell2, leaving the result in cell2. |
FLOAT cell1 | Convert the whole number in cell1 to floating point |
FLOAT (cell1) | Convert the whole number in cell1 to floating point |
It is now time to confess that we cheated in the program above: When we computed the average, we divided a whole number into the sum, and came out with a fraction. As you can see above, this will not work, and we have to convert the sum to floating point before dividing. The revised program follows:
Cell number | Contents |
---|---|
1 | JUMP 21 |
2 | DATA 6 |
3 | DATA 21 |
4 | DATA 46 |
5 | DATA 396 |
6 | DATA 134 |
7 | DATA 58 |
8 | DATA 93 |
9 | DATA 0 |
10 | DATA 0 |
11 | DATA 0 |
12 | DATA 0 |
13 | DATA 0 |
14 | DATA 0 |
15 | DATA 0 |
16 | DATA 0 |
17 | DATA 0 |
18 | DATA 0 |
19 | DATA 0 |
20 | DATA 0 |
21 | MOVE 2,20 |
22 | MOVE #0,19 |
23 | MOVE #3,18 |
24 | ADD (3),19 |
25 | ADD #1,18 |
26 | SUB #1,20 |
27 | JNZERO 20,24 |
28 | MOVE 19,17 |
29 | FLOAT 17 |
30 | FLOAT 2 |
31 | FDIV 2,17 |
32 | IFIX 2 |
33 | STOP |
We also need to note that the average in cell 17 is now returned as a floating point number.
We will add a few instructions to allow input and output:
STATUS device, cell1 | Read a status word from the device indicated
into the memory cell named.
The following devices exist:
The following information is defined for most devices:
|
READ device,cell1 | Transfer one word from the device device indicated to the memory cell named. |
WRITE device,cell1 | Transfer one word of data from the memory cell to the device |
COMMAND device,cell1 | Send the command in cell1 to the device. The commands are different for each device. |
When the program does a WRITE, an ASCII character is sent to the typewriter, which has a small buffer. OUTPUT_AVL indicates whether there is room for another character in the buffer. If the program does a WRITE when the buffer is full, the program will wait with the TTYWRITE lamp on the console turned on.
Next: BASIC