Let's see what our simple (emulated) assembly language program does from the top. Firstly the accumulator is loaded with the value 12*256 + 128 = 3200, which is just the number of text locations on the screen. After all, there are 40 lines of 80 characters each, which gives 40*80 = 3200 locations.
Next the accumulator value is exchanged with that in register 0. So now register 0 contains the counter for the screen position and the accumulator will contain whatever was in the register (which is just random rubbish at the start of the program).
Next the value A000 is loaded into the accumulator. This is the memory location of the screen memory in our machine. The next instruction LDX loads this value from the accumulator into the segment register. The next instruction then swaps this out to register 1 for safe keeping.
Next the value 131*256+65 is loaded into the accumulator. The 131 refers to the attribute of a character, whilst the 65 refers to the ASCII value of the letter A. Simply look at the output of the program to see what this data refers to. It is the data that is going to be copied into every location in screen memory, so that the screen is filled up with coloured A's.
The next instruction stores this two byte combination in the memory location addressed by the segment register, with an offset of 0. In other words, it is stored in the screen memory.
One of the many deficiencies of our assembly language shows up at this point. It would make more sense to have the segment register store the address of the screen memory, and have the offset continually updated and stored in a general purpose register. Then we would need an instruction to store the contents of the accumulator at the location pointed to by the segment register plus the contents of a specified register. This is an improvement that could easily be made to our language, and is left as an exercise for you the reader.
Next the contents of register 0 are exchanged with the accumulator. Recall that register zero stored the counter for the number of screen locations that we have to fill. The very next instruction now subtracts 1 from this value, since there is one less screen location left to fill now.
Next we compare the number of screen locations left, with 0. We want to see if there are any left to fill. This is part of a loop, which we are about to describe. The next instruction jumps, if the result of the comparison was not above. In other words, if the number of screen locations left to fill is not above zero, we jump. In this instance to location jumped to is memory location 38, which contains a HLT instruction, terminating the program. Clearly if we still have more locations to fill, this jump is not taken, and execution continues.
Next we exchange the updated screen location counter back into register 0 for safekeeping and we then swap out the contents of the register which contains the memory address stored in register 1. Recall that this contains the memory location of the screen memory that should be written to next. The next instruction adds 2 to this value and the program then jumps back to memory location 8. This basically implements a loop. For, memory location 8 contains the instruction to load the segment register with the new value stored in the accumulator, and the program continues as before, saving this value back to register 1, putting an A at the next location in screen memory and updating the loop counter again, etc.
Essentially, this program implements a complicated for loop in assembly language. It is remarkable that with such a primitive language, we can implement all the functionality of a computer. Of course each instruction that might have been written quite simply in C, requires many instructions in assembly language to do the same thing.
One final question you might be asking is, "why have a machine emulator as a project for a c tutorial?" The answer is simple. It allows us to show off much of the remaining functionality of C, and it also demonstrates that a very complex project can be implemented with a minimum of fuss in C. It took only about half a day to write this program, and yet it accomplishes quite a lot.
Do play around with the assembly language program and write some more complicated programs for yourself. You can make it do MUCH more than a simple loop. Send your efforts to the FriedSpace team. Simply email us, or log on to our forum and post your results. We'd love to see what you are doing with the emulator. Later on, we'll post a more sophisticated emulator on FriedSpace.com, so you can see what WE are doing with it.
Finally, note that we have not test all the assembly language commands, so if you find that some of them don't work as advertised, let us know, and we'll fix them. There are probably many errors!