Accessing Memory

Soon we will come to writing the code which constitutes the functionality of our machine, i.e. the code which actually takes machine code instructions which it finds in the memory of our machine and actually performs the functions requested by those instructions. When we do this, however, we will find that there are certain things the machine will want to do over and over again. This is exactly what the processor in a real world machine does too. It has certain functions that it performs over and over. In order to deal with this, designers of chips build in subunits whose job is to perform just those functions. In our case, instead of using dedicated hardware subunits, we will just use ordinary old C functions.

One function that we will need to perform often is taking two separate adjacent bytes (8 bits each) of data in the machine's memory, and converting that data into a single word (16 bits) of data. Since the C type for a byte is unsigned char and the type for a word is int, we need a procedure for extracting two bytes from our machines memory, and joining them together and returning the result as a word. This is precisely what the function fetch() does.

The function fetch() will be called from within the code that emulates the processor itself (the function emulate(). It will not be accessible from the main program portion of our code (main.c) and therefore, it does not need to be listed in the header file enulate.h. It is invisible to the rest of the world, and is only visible from inside our emulator library itself.

The actual operation of fetch() should be fairly self explanatory. It takes as parameter, an address of some location of memory within our machine. It takes the byte of data at that location and the byte at the very next memory location, and combines them together. The result is return as a word (a return value of type int). The combining process itself is very simple. Multiplying one of the bytes by 256 = 2^8, effectively shifts it to the left by 8 bits. Then adding the other byte of data to the result, gives the 16 bit value we are after.

The next function, put(), does the opposite of fetch(). It places a given 16 bit word of data into two adjacent bytes of memory, the first of which is specified by supplying its address. Thus the function put() has two parameters, address which specifies the memory location we are putting data into, and value which is the 16 bits of data that we wish to put into that location (and its neighbour).

First, we need to break that 16 bits of data apart, into two single bytes of data. This is done with a little mathematics. To get the high 8 bits of data (the 8 bits on the left of the word) we simply divide by 256, and ignore the remainder. This is the exact opposite of the multiplication we performed to get a byte up into that location, in the put() function. Note that to perform this so-called integer division which ignores any remainder after division, we simply need to use C's division function /. Well, this is not quite the whole story. The reason this slash performs an integer division, is because we are dividing two integers. In fact if we had supplied two floating point numbers instead, or even one floating point number and an integer, C would have thought we wanted to do a proper division, and would have returned a floating point number as the answer (and it would not have ignored any remainder). However, given that we are supplying two integers without decimal points, we will get an integer as our answer, just as we require.

To extract the second byte from our word, we need the remainder after dividing by 256. This time we are not interested in the quotient, but we actually want the remainder, which we ignored when we were after the left hand byte. The function for returning a remainder after division is %. It is the function used for performing so-called modular arithmetic. We won't go into this here, since it isn't important for us now, but it is very important to mathematicians, and has quite a lot of uses in computer science too.