The Machine Description

So now we can describe our machine in detail. Our processor will contain one special register, called an accumulator, (whose name will be the unimaginative, A), which will have special functionality. Almost everything our chip can do, is done through the accumulator. Data brought in from memory must first go into the accumulator, and any logical or arithmetic operations get performed on the data in the accumulator.

As well as the accumulator, there will be 7 other general data registers, simply numbered 0 through 6. They will be used for storing intermediate values of computations, a bit like variables in a C program. They will not offer any special functions, except in the case of multiplying numbers, where numbers larger than 16 bits occur, in which case, one of the registers will be used in addition to the accumulator to store the result of the multiplication.

Any location in memory can be referred to by our processor and by its associated assembly language, by giving the location in memory as a 16 bit number. In other words, a memory location will be referred to (or addressed) by a number from 0 to 65535 (a total of 65536 locations). Our assembly language and processor will provide for this in a number of ways. Firstly, an address could be specified in our assembly code, just by giving the address (i.e. 16 bit number) of the location. Secondly, there will be a special register, called a segment register, and named X, which will hold an address. Thirdly, in assembly language, we will be able to specify an address as being the sum of the value in the segment register X, and some offset, i.e. a 16 bit number which tells the processor how far past the location specified by X, that the location of interest resides. This last feature is useful for implementing the assembly language equivalent of arrays. The segment register contains the location of the start of the array, whilst the offset (specified by a 16 bit number in the assembly code itself) specifies which entry in the array to access.

Our processor will also possess three flags. These are one bit stores which report information about the most recently completed computation. There will be three flags, denoted C, P and Z. These flags are the carry flag, which is set to one when the result of an addition results in a carry, and zero otherwise, the sign flag, which reports whether the result of the most recent computation was a positive number or not, and the zero flag, which reports whether the result was zero or not. These flags are used to control program flow. Assembly language doesn't have complicated if, then, else statements like high level languages. Basically, you can jump to wherever you like in code and optionally base the decision to jump or not, on the value of one or more of the flags.

Finally the processor will possess another register called SP, for stack pointer. It will refer to a location in memory where a stack is located. It will always refer to the top of the stack, which in our unusual machine (though not unusual compared to the real world in this case), will actually be the lowest memory location being used for the stack. In other words, the stack will fill up from the top of the memory down. The stack will always start at memory location A000 (this is hexadecimal notation, where there are 2^4 = 16 digits, numbered 0 through 9, A, B, C, D, E, F. It is just a shorthand for binary notation. Each hexadecimal digit stands for 4 binary bits, so that A000 codes for 1010 0000 0000 0000 which means 2^15 + 2^13 = 32768 + 8192 = 40960). As items are stored in the stack, they will be placed in the location immediately below that addressed by the stack pointer, and the value in the stack pointer will automatically be adjusted to point to this new data. As data is taken back off the stack, the reverse happens, and the stack pointer automatically adjusts up in value.

Now I said that the stack pointer was the final feature of our machine. Well, actually there is one more register, called IP for index pointer. It is completely internal to our processor and cannot be directly accessed by the assembly language for our machine. Instead, it silently keeps track of which memory location the processor is up to in its execution. Obviously the program which our processor is executing is also contained in the the memory of our machine, and the processor needs to keep track of where it is up to in the program that is running. That is the function of the index pointer. When a program branches off to run a subroutine, or it jumps off to a different part of the code due to a jump or conditional jump instruction, the value of the index pointer changes to point to the new part of the code that is to be executed. Also, after every instruction is executed, the index pointer is updated to point to the next instruction in memory. The index pointer is part of the internal implementation of any self respecting processor, and it is something that we also can't do without.

We'll explain more about the specifics of how our machine works, as we implement it. For now you have a basic idea in your head that there is some kind of processor, which understands a fictitious assembly language, which has instructions for shunting data around, from memory, to registers and back to memory again.