education
Coding an Assembler Interpreter in Runtime Revolution
02/07/07 11:16 Filed in: Runtime Revolution
The problem
Since the beggining of the year, I am a computer science undergrad student. There in my new university, they are teaching me the joys and pains of learning about programming, hardware architecture and the like. Most of my fellow classmates never coded in their life and actually, some had no clue about how programming languages work. They teach us, two chairs in the first semester that involves programming.Programming Techniques 101: Our first formal introduction to programming and the newbie friendly and very readable language they choose to use was C, and it gets even better, we're using Turbo C from Borland circa 1991. I am only able to follow it because I actually learned to program using Turbo C in *1993* (give or take couple years). But that is not a post about C, it is about the other chair.
Computer Architecture 101: Here we learn about bits and bytes, cpus, memories and all the hardware that is made in china, sold in the us and smuggled to brazil. And here we learn Assembler. Students are supposed to learn to code in assembler for a non-existant x86 machine. For that we use some simulator called SIMx86 that has a newbie oriented assembler with commands such as GET that requests a numerical input from the keyboard. Our second examination was just made of assembler questions.
The problem, I skipped the assembler classes, I didn't knew how to code in SIMx86 assembler! The bigger problem, SIMx86 just run on Win32 machines and I have four macs. It was 10:00 PM, the exam was in 10 hours, I decided that learning that assembler using my paper lectures was not as good because I couldn't test to see if my code was really working and then I decided to undertake a huge project, code my own assembler simulator for the language used in SIMx86.
The result
A picture is worth a thousand typos, here goes a shot
This is my finished assembler simulator, it can run all the examples we learned in class, it has a poor man debugger that allow me to step thru the code line by line checking registers. The missing part is memory access, right now I just implemented the registers, no access and manipulation of memory addresses but I'll in the future add a 64k memory.
The whole interpreter code is just 164 lines of transcript. It was fairly easy to do, the hardest part was the fact that SIMx86 math is all hexadecimal based and rev is all base 10, so I had to convert numbers before displaying and after input, that is not a problem *if you think of it before coding* it took me two hours to remember that values should be hexadecimal and that was why my code was failing.
My interpreter has functions for adding and subtracting, conditional jumps, labels, some bitwise operations and variable copying. It can run all code we used in the class and even better, it allows one to step thru. I also added context sensitive help, when stepping thru, a little field contains all the info available for the current command being executed.
I finished coding this at 2:00 AM, the examination was at 7:30 AM.... it was not the wisest decision on earth, I used many hours to code and fine tune my own assembler interpreter when I should be studying. I am waiting for my grade on that examination, but no matter if I have a good or bad grade, I am proud of my silly interpreter, it even sports a nice eMac monitor for displaying the output.
The implementation
Implementing this interpreter was easy. There are couple script local variables:- theSource - holds the source being executed.
- tCL - the current line we're executing.
- ax, bx, cx, dx - the registers.
- t1, t2 - holds values for conditional implementation such as CMP AX, BX.
Then it is all done with two main functions - ExecuteASM and GetNextLine.
GetNextLine
it picks the line tCL of theSource and passes to ExecuteASM, it increments tCL then. Simple as that.
ExecuteASM
This function executes one Assembly instruction, it uses some helper functions such as ParseRegister to find values for the register and SetRegister to push back the values but it is all a big switch statement. If the "step line by line" checkmark button is not hilited, this function will call GetNextLine before finishing, if it is hilited then it just finishes and you can move to the next line by pressing the execute button which calls GetNextLine.
Interpreter is initialized by a function called StartASM, this function zeroes the registers and move tCL (the current line) to the first line in the source. This is called on closeField of field "source" and also when tCL is the first line. This is how we refresh the interpreter after execution, when the HALT command is found we put 1 into tCL, so when GetNextLine happens, it will call StartASM for it is on the first line.
I am very proud of my conditionals and jumping. It was so easy to implement that in Revolution, I simply use lineOffset to find the line that contains the label and then change tCL to be that line, the next call to GetNextLine will execute from that line. All jumps, switches and loops are now easy to implement.
This is a simple story of how someone with raw knowledge of Assembly and some better knowledge of Revolution was able to implement in less than five hours, a simple intepreter to help him study for an examination. This is what I think Dan Shafer called the inventive user, that creates impromptu tools as the need arises, my own Assembly interpreter is not a product, it is a simple tool that helped me get a better grasp of how that language works and allowed me to experiment before an examination. Bonus it works on Macs, Windows and probably linux (without the blends).
|