Instructions for Lab 7

The textual shell

So far we had no way of using the machine interactively. We will design a little shell that repeatedly waits for a command, interprets it, and sends the appropriate request to the machine. Here is an example:
> more duckMachine/test1.o
# Object file format: Every line should be:
# address instruction
# or
# address data
# or consisting of white space only
# Obviously # marks the beginning of a comment.

0 	in 10         # input a value and store it in location 10
1 	increment 10 
2 	out 10        # result should be input value + 1
3 	halt
>
> java duckMachine.Text
DM>> load duckMachine/test1.o
DM>> kkkkkkk
duckMachine.operatingSystem.ShellE: Unknown Command kkkkkkk
DM>> run duckMachine/operatingSystem/DebugIns.java
IN 10
88
	PC=1	ACC=0	GT/EQ/LT=false/false/false

INCREMENT 10
	PC=2	ACC=0	GT/EQ/LT=false/false/false

OUT 10
89
	PC=3	ACC=0	GT/EQ/LT=false/false/false

HALT
DM>> setPC 0
DM>> run duckMachine/operatingSystem/ExecIns.java
88
89
DM>> setPC 1
DM>> step duckMachine/operatingSystem/ExecTraceIns.java
INCREMENT 10
DM>> quit
Before you go any further, try to run the above script yourself using my class files. If you haven't done so already, now would be a great time to get all of my class files and test them.

Object File Loader

In the previous assignment, we've performed the following sequence of actions to load a program into memory: Instead we would like to write the program in a file (called an object file) and automate all the above steps. The format of our object files is rather simple. For example here is the sample object file used above:
# Object file format: Every line should be:
# address instruction
# or
# address data
# or consisting of white space only
# Obviously # marks the beginning of a comment.

0 	out 10
1 	increment 10
2 	out 10
3 	increment 10
4 	out 10
5 	halt
10 	42
In addition to instructions, an object file may contain data to be loaded at specific addresses in memory. These data items are constants used in the source program. The task of the object file loader is to read an object file conforming to the above format and load it in the memory of the machine. In order to do that, the loader must perform lexical analysis and parsing. The lexical analysis consists of grouping related characters together. For example, the three characters 'o', 'u', and 't' at line 4 should be grouped together in a string representing an opcode. Also the lexical analyzer should ignore the comments and the white space. The second task is to parse the input characters in meaningful entities. For example, the string "halt" should not be followed by an address, but every other string representing an instruction should have an additional address parameter. Also some strings do not represent any known opcode and hence are illegal. For example, every line in the following file is erroneous:
1	halt 88		# halt instructions do not have an address argument
2	divide 17	# there is no opcode divide
	add 12		# missing address

Lexical Analysis

Fortunately all of the functions of our lexical analyzer are almost entirely automated by Java's StreamTokenizer's class, which skips white space and comments, and groups the remaining characters into meaningful tokens such as numbers and strings. The code to create and customize the lexical analyzer is essentially:
     BufferedReader cr = new BufferedReader (new FileReader (filename));
     reader = new StreamTokenizer (cr);
     reader.commentChar('#');

Parsing

In general parsing is performed using specialized tools, called parser generators, that take a specification of the grammar and automatically produce the parsing code. In our case, the structure of the object files is so simple that it is easier to write the parsing code directly. The main loop of the parser is the following:
  public Enumeration parse () throws ObjectFileE { 
    Vector result = new Vector();
    try {
      while (true) {
	LoadableWord p = parseLine();
	result.addElement(p);
      }
    }
    catch (EOF e) {
      return result.elements();
    }
  }
The parser loops until it encounters the EOF. Each line is processed to return a LoadableWord as required by the machine's load method. Parsing a line begins by calling reader.nextToken() to read the next token, and then performs a case analysis based on the kind of token read.
      if (reader.ttype == reader.TT_EOF) ...

      if (reader.ttype == reader.TT_NUMBER) ...
      
      if (reader.ttype == reader.TT_WORD) ...

To Do

Implement a class ObjectFile using the above guidelines. The constructor should have the following signature:
  public ObjectFile (String filename) throws ObjectFileE
The exception ObjectFileE is thrown if the file is not found.


Visited times since December 15, 1997 (or the last crash).

sabry@cs.uoregon.edu