5.1 Developing and compiling user programs

Nachos cross-compiler allows programmers to write C user programs and compile to COFF binaries that can be executed on the Nachos MIPS simulator. COFF stands for Common Object File Format and is an industry-standard binary format which the Nachos kernel understands. The cross-compiler itself is platform-dependent (though the COFF binary is not) and therefore one needs to make sure the correct one is used.

The following code is an example of C user program (nachos/test/cp.c).

1  #include "syscall.h"
2  #include "stdio.h"
3  #include "stdlib.h"
4  
5  #define BUFSIZE 1024
6  
7  char buf[BUFSIZE];
8  
9  int main(int argc, char⋆⋆ argv)
10  {
11    int src, dst, amount;
12  
13    if (argc!=3) {
14      printf("Usage: cp <src> <dst>\n");
15      return 1;
16    }
17  
18    src = open(argv[1]);
19    if (src==-1) {
20      printf("Unable to open %s\n", argv[1]);
21      return 1;
22    }
23  
24    creat(argv[2]);
25    dst = open(argv[2]);
26    if (dst==-1) {
27      printf("Unable to create %s\n", argv[2]);
28      return 1;
29    }
30  
31    while ((amount = read(src, buf, BUFSIZE))>0) {
32      write(dst, buf, amount);
33    }
34  
35    close(src);
36    close(dst);
37  
38    return 0;
39  }

The corresponding COFF binary is also located in the nachos/test directory. This is the default directory for user programs. Alternatively, one can specify the test directory by including a line fileSystem.testDirectory = ... in the config file.

Question: Where and how does Nachos set the test directory? [hint: Check nachos.machine.Machine.main()]

Inspecting the cp.c source code, we find that it follows the C syntax with familiar functions such as printf, open, etc. However, a closer look at the test directory and Makefile reveals that some of the functions are in fact implemented by Nachos in the test directory. The function prototypes of system calls such as creat, open, read, write, close, halt, etc., are defined in syscall.h and their implementations are to be completed in the one of the Nachos projects.

There are multiple stages to building a Nachos-compatible MIPS binary (all of which are handled by the test Makefile):

  1. Source files (*.c) are compiled into object files (*.o) by mips-gcc.
  2. start.s is preprocessed and assembled into start.o. This file contains the assembly-language code to initialize a process. It also provides the system call ”stub code” which allows system calls to be invoked. This makes use of the special MIPS instruction syscall which traps to the Nachos kernel to invoke a system call.
  3. An object file is linked with libnachos.a to produce a Nachos-compatible MIPS binary, which has the extension *.coff.
  4. Note that if you create a new test file (*.c), you will need to append your program name to the variable TARGETS in the Makefile inside test directory

One can run test programs by running “nachos -x PROGNAME.coff”. In nachos.conf, the appropriate kernel and process need to be specified:

1  Machine.stubFileSystem = true
2  Machine.processor = true
3  Machine.console = true
4  ...
5  Kernel.processClassName = nachos.userprog.UserProcess
6  Kernel.kernel = nachos.userprog.UserKernel

subFileSystem is enabled to load the user program.