Getting started
***************

In this chapter, you will find a sample code-compile-run-debug session using the MDK utilities. Familiarity with the MIX mythical computer and its assembly language MIXAL (as described in Knuth's TAOCP) is assumed; for a compact reminder, see MIX and MIXAL tutorial.

Writing a source file
=====================

MIXAL programs can be written as ASCII files with your editor of choice. Here you have the mandatory hello world as written in the MIXAL assembly language:

     *                                                        (1)
     * hello.mixal: say 'hello world' in MIXAL                (2)
     *                                                        (3)
     * label ins    operand     comment                       (4)
     TERM    EQU    19          the MIX console device number (5)
             ORIG   1000        start address                 (6)
     START   OUT    MSG(TERM)   output data at address MSG    (7)
             HLT                halt execution                (8)
     MSG     ALF    "MIXAL"                                   (9)
             ALF    " HELL"                                   (10)
             ALF    "O WOR"                                   (11)
             ALF    "LD   "                                   (12)
             END    START       end of the program            (13)

MIXAL source files should have the extension .mixal when used with the MDK utilities. As you can see in the above sample, each line in a MIXAL file can be divided into four fields separated by an arbitrary amount of white space characters (blanks and/or tabs). While in Knuth's definition of MIXAL each field must start at a fixed predefined column number, the MDK assembler loosens this requirement and lets you format the file as you see fit. The only restrictions retained are for comment lines (like 1-4), which must begin with an asterisk (*) placed at column 1, and for the label field (see below) which, if present, must also start at column 1. The four fields in each non-comment line are:

  * an optional label, which either refers to the current memory address (as START and MSG in lines 7 and 9) or a defined symbol (TERM) (if present, the label must always start at the first column in its line, because the first white space in the line marks the beginning of the second field),

  * an operation mnemonic, which can represent either a MIX instruction (OUT and HLT in lines 7 and 8 above) or an assembly pseudoinstruction (e.g., the ORIG pseudoinstruction in line 6 (If an ORIG directive is not used, the program will be loaded by the virtual machine at address 0. ORIG allows you to allocate the executable code where you see fit.)).

  * an optional operand for the (pseudo)instruction, and

  * an optional free text comment.

Lines 9-12 of the hello.mixal file above also show the second (and last) difference between Knuth's MIXAL definition and ours. In our version, the operand of the ALF pseudoinstruction (a word of five characters) must be quoted using "". (In Knuth's definition, the operand always starts at a fixed column number, and the use of quotation is therefore unnecessary. As mixasm releases this requirement, marking the beginning and end of the ALF operand disambiguates the parser's recognition of this operand when it includes blanks. Note that double-quotes (") are not part of the MIX character set, and, therefore, no escape characters are needed within ALF's operands.)

The workings of this sample program should be straightforward if you are familiar with MIXAL. See TAOCP vol. 1 for a thorough definition or MIX and MIXAL tutorial, for a tutorial.

Compiling
=========

Three simulators of the MIX computer, called mixvm, gmixvm and mixguile, are included in the MDK tools. They are able to run binary files containing MIX instructions written in their binary representation. You can translate MIXAL source files into this binary form using mixasm, the MIXAL assembler. So, in order to compile the hello.mixal file, you can type the following command at your shell prompt:

     mixasm -g hello

If the source file contains no errors, this will produce a binary file called hello.mix which can be loaded and run by the MIX virtual machine. The -g flag tells the assembler to include debug information in the executable file (for a complete description of all the compilation options, see mixasm). Now, you are ready to run your first MIX program, as described in the following section.

Running the program
===================

MIX is a mythical computer, so it is no use ordering it from your favorite hardware provider. MDK provides three software simulators of the computer, though. They are:

  * mixvm, a command line oriented simulator,

  * gmixvm, a GTK based graphical interface to mixvm, and

  * mixguile, a Guile shell with a built-in MIX simulator.

All three simulators accept the same set of user commands, but offer a different user interface, as noted above. In this section we will describe some of these commands and show you how to use them from mixvm's command line. You can also use them at gmixvm's command prompt (see gmixvm), or with the built-in Scheme primitives of mixguile (see Using mixguile).

Using the MIX simulators, you can run your MIXAL programs, after compiling them with mixasm into binary .mix files. mixvm can be used either in interactive or non-interactive mode. In the second case, mixvm will load your program into memory, execute it (producing any output due to MIXAL OUT instructions present in the program), and exit when it encounters an HLT instruction. In interactive mode, you will enter a shell prompt which allows you to issue commands to the running virtual machine. This command will permit you to load, run and debug programs, as well as inspect the MIX computer state (register contents, memory cells contents and so on).

Non-interactive mode
--------------------

To make mixvm work in non-interactive mode, use the -r flag. Thus, to run our hello.mix program, simply type:

     mixvm -r hello

at your command prompt, and you will get the following output:

     MIXAL HELLO WORLD

Since our hello world program uses MIX's device number 19 as its output device (see Writing a source file), the output is redirected to the shell's standard output. Had you used any other MIX output devices (disks, drums, line printer, etc.), mixvm would have created a file named after the device used (e.g. disk4.dev) and written its output there. (The device files are stored, by default, in a directory called .mdk, which is created in your home directory the first time mixvm is run. You can change this default directory using the command devdir when running mixvm in interactive mode (see Configuration commands).)

The virtual machine can also report the execution time of the program, according to the (virtual) time spent on each of the binary instructions (see Execution times). Printing of execution time statistics is activated with the -t flag; running:

     mixvm -t -r hello

produces the following output:

     MIXAL HELLO WORLD
     ** Execution time: 11

Sometimes, you will prefer to store the results of your program in MIX registers rather than writing them to a device. In such cases, mixvm's -d flag is your friend. It makes mixvm dump the contents of its registers and flags after executing the loaded program. For instance, typing the following command at your shell's prompt:

     mixvm -d -r hello

you will obtain the following output:

     MIXAL HELLO WORLD
     rA: + 00 00 00 00 00 (0000000000)
     rX: + 00 00 00 00 00 (0000000000)
     rJ: + 00 00 (0000)
     rI1: + 00 00 (0000)     rI2: + 00 00 (0000)
     rI3: + 00 00 (0000)     rI4: + 00 00 (0000)
     rI5: + 00 00 (0000)     rI6: + 00 00 (0000)
     Overflow: F
     Cmp: E

which, in addition to the program's outputs and execution time, gives you the contents of the MIX registers and the values of the overflow toggle and comparison flag (admittedly, rather uninteresting in our sample).

As you can see, running programs non-interactively has many limitations. You cannot peek the virtual machine's memory contents, step through your program's instructions, or set breakpoints. (The mixguile program allows you to execute arbitrary combinations of mixvm commands (using Scheme) non-interactively. See Scheme scripts.) Enter interactive mode.

Interactive mode
----------------

To enter the MIX virtual machine's interactive mode, simply type:

     mixvm

at your shell command prompt. This command starts the mixvm command shell. You will be presented with the following command prompt:

     MIX >

The virtual machine is initialized and ready to accept your commands. The mixvm command shell uses GNU's readline, so you have at your disposal command completion (using TAB) and history functionality, as well as other line editing shortcuts common to all utilities using this library. (For a complete description of readline's line editing usage, see Command Line Editing (Readline).)

Usually, the first thing you will want to do is load a compiled MIX program into memory. This is accomplished by the load command, which takes as an argument the name of the .mix file to be loaded. Thus, typing:

     MIX > load hello
     Program loaded. Start address: 3000
     MIX >

will load hello.mix into the virtual machine's memory and set the program counter to the address of the first instruction. You can obtain the contents of the program counter using the command pc:

     MIX > pc
     Current address: 3000
     MIX >

After loading it, you are ready to run the program, using, as you surely have guessed, the run command:

     MIX > run
     Running ...
     MIXAL HELLO WORLD
     ... done
     Elapsed time: 11 /Total program time: 11 (Total uptime: 11)
     MIX >

Note that now the timing statistics are richer. You obtain the elapsed execution time (i.e., the time spent executing instructions since the last breakpoint), the total execution time for the program up to now (which in our case coincides with the elapsed time, since there were no breakpoints), and the total uptime for the virtual machine (you can load and run more than one program in the same session). (Printing of timing statistics can be disabled using the command timing (see Configuration commands).) After running the program, the program counter will point to the address after the one containing the HLT instruction. In our case, asking the value of the program counter after executing the program will give us:

     MIX > pc
     Current address: 3002
     MIX >

You can check the contents of a memory cell by giving its address as an argument of the command pmem, like this:

     MIX > pmem 3001
     3001: + 00 00 00 02 05 (0000000133)
     MIX >

and convince yourself that address 3001 contains the binary representation of the instruction HLT. An address range of the form FROM-TO can also be used as the argument of pmem:

     MIX > pmem 3000-3006
     3000: + 46 58 00 19 37 (0786957541)
     3001: + 00 00 00 02 05 (0000000133)
     3002: + 14 09 27 01 13 (0237350989)
     3003: + 00 08 05 13 13 (0002118477)
     3004: + 16 00 26 16 19 (0268542995)
     3005: + 13 04 00 00 00 (0219152384)
     3006: + 00 00 00 00 00 (0000000000)
     MIX >

In a similar manner, you can look at the contents of the MIX registers and flags. For instance, to ask for the contents of the A register you can type:

     MIX > preg A
     rA: + 00 00 00 00 00 (0000000000)
     MIX >

Use the command help to obtain a list of all available commands, and help COMMAND for help on a specific command, e.g.:

     MIX > help run
     run             Run loaded or given MIX code file. Usage: run [FILENAME]
     MIX >

For a complete list of commands available at the MIX prompt, see mixvm. In the following subsection, you will find a quick tour through commands useful for debugging your programs.

Debugging commands
------------------

The interactive mode of mixvm lets you do step-by-step execution of programs as well as set breakpoints. Use next to step through the program, running its instructions one by one. To run our two-instruction hello.mix sample you can do the following:

     MIX > load hello
     Program loaded. Start address: 3000
     MIX > pc
     Current address: 3000
     MIX > next
     MIXAL HELLO WORLD
     Elapsed time: 1 /Total program time: 1 (Total uptime: 1)
     MIX > pc
     Current address: 3001
     MIX > next
     End of program reached at address 3002
     Elapsed time: 10 /Total program time: 11 (Total uptime: 11)
     MIX > pc
     Current address: 3002
     MIX > next
     MIXAL HELLO WORLD
     Elapsed time: 1 /Total program time: 1 (Total uptime: 12)
     MIX >
     MIX > run
     Running ...
     ... done
     Elapsed time: 10 /Total program time: 11 (Total uptime: 22)
     MIX >

The above sample also shows how the virtual machine handles cumulative time statistics and automatic program restart.

You can set a breakpoint at a given address using the command sbpa (set breakpoint at address). When a breakpoint is set, run will stop before executing the instruction at the given address. Typing run again will resume program execution. Coming back to our hello world example, we would have:

     MIX > sbpa 3001
     Breakpoint set at address 3001
     MIX > run
     Running ...
     MIXAL HELLO WORLD
     ... stopped: breakpoint at line 8 (address 3001)
     Elapsed time: 1 /Total program time: 1 (Total uptime: 23)
     MIX > run
     Running ...
     ... done
     Elapsed time: 10 /Total program time: 11 (Total uptime: 33)
     MIX >

Note that, since we compiled hello.mixal with debug info enabled (the -g flag of mixasm), the virtual machine is able to tell us the line in the source file corresponding to the breakpoint we are setting. As a matter of fact, you can directly set breakpoints at source code lines using the command sbp LINE_NO, e.g.:

     MIX > sbp 4
     Breakpoint set at line 7
     MIX >

sbp sets the breakpoint at the first meaningful source code line. Since in the above example we have requested a breakpoint at a line that does not correspond to a MIX instruction, the breakpoint is set at the first line after the given one that contains a real instruction after the given one. To unset breakpoints, use cbpa ADDRESS and cbp LINE_NO, or cabp to remove all currently set breakpoints. You can also set conditional breakpoints, i.e., tell mixvm to interrupt program execution whenever a register, a memory cell, the comparison flag or the overflow toggle change, using the command sbp[rmco] (see Debug commands).

MIXAL lets you define symbolic constants by either using the EQU pseudoinstruction or starting an instruction line with a label (which assigns to the label the value of the current memory address). Each MIXAL program has, therefore, an associated symbol table which you can inspect using the psym command. For our hello world sample, you will obtain the following output:

     MIX > psym
     START:  3000
     TERM:  19
     MSG:  3002
     MIX >

Other useful commands for debugging are strace (which turns on tracing of executed instructions), pbt (which prints a backtrace of executed instructions) and weval (which evaluates w-expressions on the fly). For a complete description of all available MIX commands, see mixvm

Using mixguile
==============

With mixguile you can run a MIX simulator embedded in a Guile shell, using Scheme functions and programs. As with mixvm, mixguile can be run both in interactive and non-interactive modes. The following subsections provide a quick tour through the use of this MIX emulator.

The mixguile shell
------------------

If you simply type:

     mixguile

at the command prompt, you'll be presented with a Guile shell prompt like this:

     guile>

At this point, you have entered a Scheme read-eval-print loop (REPL) which offers you all the Guile functionality plus a new set of built-in procedures to execute and debug MIX programs. Each of the mixvm commands described in the previous sections (also see mixvm) has a Scheme function counterpart named after it by adding the prefix mix- to its name. Thus, to load our hello world program, you can simply enter:

     guile> (mix-load "hello")
     Program loaded. Start address: 3000
     guile>

You can then run it using mix-run:

     guile> (mix-run)
     Running ...
     MIXAL HELLO WORLD
     ... done
     Elapsed time: 11 /Total program time: 11 (Total uptime: 11)
     guile>

You can also execute it step-by-step using the Scheme function mix-next or set a breakpoint:

     guile> (mix-sbp 4)
     Breakpoint set at line 5
     guile>

or, if you want to peek at a register's contents:

     guile> (mix-preg 'A)
     rA: + 00 00 00 00 00 (0000000000)
     guile>

You get the idea. You have at your disposal all the mixvm and gmixvm commands by means of mix- functions. But, in case you are wondering, this is only the beginning. You also have at your disposal a whole Scheme interpreter. You can, for instance, define new functions by combining the mix- commands and any of the other Scheme primitives. In the next sections, you'll find examples of how to take advantage of the Guile interpreter.

Additional MIX Scheme functions
-------------------------------

The mix- function counterparts of the mixvm commands don't return any value, and are evaluated only for their side-effects (possibly including informational messages to the standard output and/or error stream). When writing your own Scheme functions to manipulate the MIX virtual machine within mixguile (see Defining new functions), you'll probably need Scheme functions returning the value of the registers, memory cells and so on. Don't worry: mixguile does also offer you such functions. For instance, to access the (numerical) value of a register you can use mix-reg:

     guile> (mix-reg 'I2)
     0
     guile>

Note that, unlike (mix-preg 'I2), the expression (mix-reg 'I2) in the above example evaluates to a Scheme number and does not produce any side-effect:

     guile> (number? (mix-reg 'I2))
     #t
     guile> (number? (mix-preg 'I2))
     rI2: + 00 00 (0000)
     #f
     guile>

In a similar fashion, you can access the memory contents using (mix-cell), or the program counter using (mix-loc):

     guile> (mix-cell 3000)
     786957541
     guile> (mix-loc)
     3002
     guile>

Other functions returning the contents of the virtual machine components are mix-cmp and mix-over, which evaluate to the value of the comparison flag and the overflow toggle respectively. For a complete list of these additional functions, see mixguile.

In the next section, we'll see examples that use these functions to extend mixguile's functionality.

Defining new functions
----------------------

Scheme is a powerful language, and you can use it inside mixguile to easily extend the MIX interpreter's capabilities.  For example, you can easily define a function that loads a file, prints its name, executes it, and shows the registers' contents, all in one shot:

     guile> (define my-load-and-run
              (lambda (file)
                (mix-load file)
                (display "File loaded: ")
                (mix-pprog)
                (mix-run)
                (mix-preg)))
     guile>

and use it to run your programs:

     guile> (my-load-and-run "hello")
     Program loaded. Start address: 3000
     File loaded: hello.mix
     Running ...
     MIXAL HELLO WORLD
     ... done
     Elapsed time: 11 /Total program time: 11 (Total uptime: 33)
     rA: + 00 00 00 00 00 (0000000000)
     rX: + 00 00 00 00 00 (0000000000)
     rJ: + 00 00 (0000)
     rI1: + 00 00 (0000)	rI2: + 00 00 (0000)
     rI3: + 00 00 (0000)	rI4: + 00 00 (0000)
     rI5: + 00 00 (0000)	rI6: + 00 00 (0000)
     guile>

Or, maybe, you want a function that sets a breakpoint at a specified line number before executing the program:

     guile> (define my-load-and-run-with-bp
              (lambda (file line)
                (mix-load file)
                (mix-sbp line)
                (mix-run)))
     guile> (my-load-and-run-with-bp "samples/primes" 10)
     Program loaded. Start address: 3000
     Breakpoint set at line 10
     Running ...
     ... stopped: breakpoint at line 10 (address 3001)
     Elapsed time: 1 /Total program time: 1 (Total uptime: 45)
     guile>

As a third example, the following function loads a program, runs it and prints the contents of the memory between the program's start and end addresses:

     guile> (define my-run
              (lambda (file)
                (mix-load file)
                (let ((start (mix-loc)))
                  (mix-run)
                  (mix-pmem start (mix-loc)))))
     guile> (my-run "hello")
     Program loaded. Start address: 3000
     Running ...
     MIXAL HELLO WORLD
     ... done
     Elapsed time: 11 /Total program time: 11 (Total uptime: 11)
     3000: + 46 58 00 19 37 (0786957541)
     3001: + 00 00 00 02 05 (0000000133)
     3002: + 14 09 27 01 13 (0237350989)
     guile>

As you can see, the possibilities are virtually unlimited. Of course, you don't need to type a function definition each time you start mixguile. You can write it in a file, and load it using Scheme's load function. For instance, you can create a file named functions.scm with your definitions (or any Scheme expression) and load it at the mixguile prompt:

     guile> (load "functions.scm")

Alternatively, you can make mixguile load it for you automatically. When mixguile starts, it looks for a file named mixguile.scm in your MDK configuration directory (~/.mdk) and, if it exists, loads it before entering the REPL. Therefore, you can copy your definitions into that file, or load the functions.scm file from mixguile.scm.

Hook functions
--------------

Hooks are functions called before or after a given event occurs. In mixguile, you can define command and break hooks, which are associated, respectively, with command execution and program interruption events. The following sections give you a tutorial on using hook functions within mixguile.

Command hooks
.............

In the previous section, we have seen how to extend mixguile's functionality through the use of user-defined functions. Frequently, you'll write new functions that improve in some way the workings of a built-in mixvm command, following this pattern:

 a. Prepare the command execution

 b. Execute the desired command

 c. Perform post execution operations

We call the functions executed in step (a) pre-hooks, and those in step (c) post-hooks of the given command. mixguile lets you specify pre- and post-hooks for any mixvm command using the mix-add-pre-hook and mix-add-post-hook functions, which take as arguments a symbol naming the command and the function to be executed. In other words, mixguile will execute steps (a) and (c) whenever you evaluate (b). The hook functions must take a single argument, which is a string list of the command's arguments. As an example, let us define the following hooks for the next command:

     (define next-pre-hook
       (lambda (arglist)
         (mix-slog #f)))

     (define next-post-hook
       (lambda (arglist)
         (display "Stopped at line ")
         (display (mix-src-line-no))
         (display ": ")
         (display (mix-src-line))
         (newline)
         (mix-slog #t)))

In these functions, we are using the function mix-slog to turn off the informational messages produced by the virtual machine, since we are providing our own in the post-hook function. To install these hooks, we would write:

     (mix-add-pre-hook 'next next-pre-hook)
     (mix-add-post-hook 'next next-post-hook)

Assuming we have put the above expressions in mixguile's initialization file, we would obtain the following results when evaluating mix-next:

     guile> (mix-next)
     MIXAL HELLO WORLD
     Stopped at line 6:             HLT
     guile>

As a second more elaborate example, let's define hooks that print the address and contents of a cell being modified using smem. The hook functions could be something like this:

     (define smem-pre-hook
       (lambda (arglist)
         (if (eq? (length arglist) 2)
             (begin
               (display "Changing address ")
               (display (car arglist))
               (newline)
               (display "Old contents: ")
               (display (mix-cell (string->number (car arglist))))
               (newline))
             (error "Wrong arguments" arglist))))

     (define smem-post-hook
       (lambda (arglist)
         (if (eq? (length arglist) 2)
             (begin
               (display "New contents: ")
               (display (mix-cell (string->number (car arglist))))
               (newline)))))

and we can install them using

     (mix-add-pre-hook 'smem smem-pre-hook)
     (mix-add-post-hook 'smem smem-post-hook)

Afterwards, a sample execution of mix-smem would look like this:

     guile> (mix-smem 2000 100)
     Changing address 2000
     Old contents: 0
     New contents: 100
     guile>

You can add any number of hooks to a given command. They will be executed in the same order in which they are registered. You can also define global post- or pre- hooks, which will be called whenever any mixvm command is executed. Global hook functions must admit two arguments: a string naming the invoked command and a string list of its arguments. They are installed using the Scheme functions mix-add-global-pre-hook and mix-add-global-post-hook. A simple example of a global hook would be:

     guile> (define pre-hook
              (lambda (cmd args)
                (display cmd)
                (display " invoked with arguments ")
                (display args)
                (newline)))
     guile> (mix-add-global-pre-hook pre-hook)
     ok
     guile> (mix-pmem 120 125)
     pmem invoked with arguments (120-125)
     0120: + 00 00 00 00 00 (0000000000)
     0121: + 00 00 00 00 00 (0000000000)
     0122: + 00 00 00 00 00 (0000000000)
     0123: + 00 00 00 00 00 (0000000000)
     0124: + 00 00 00 00 00 (0000000000)
     0125: + 00 00 00 00 00 (0000000000)
     guile>

Note that if you invoke mixvm commands within a global hook, their associated command hooks will also be run. Thus, if you have installed both the next hooks described earlier and the global hook above, executing mix-next will yield the following result:

     guile> (mix-next 5)
     next invoked with arguments (5)
     slog invoked with arguments (off)
     MIXAL HELLO WORLD
     Stopped at line 7: MSG         ALF   "MIXAL"
     slog invoked with arguments (on)
     guile>

Adventurous readers may see the above global hook as the beginning of a command log utility or a macro recorder that saves your commands for replay.

Break hooks
...........

We have seen in the previous section how to associate hooks to command execution, but this is not the whole story. You can also associate hook functions to program interruption, specifying functions that should be called every time the execution of a MIX program is stopped due to the presence of a breakpoint, either explicit or conditional. Break hooks take as arguments the line number and memory address at which the break occurred. A simple hook that logs the line and address of the breakpoint could be defined as:

     (define break-hook
       (lambda (line address)
         (display "Breakpoint encountered at line ")
         (display line)
         (display " and address ")
         (display address)
         (newline)))

and installed for explicit and conditional breakpoints using:

     (mix-add-break-hook break-hook)
     (mix-add-cond-break-hook break-hook)

After that, every time the virtual machine encounters a breakpoint, break-code will be evaluated automatically.  (You may have noticed that break hooks can be implemented in terms of command hooks associated to mix-run and mix-next. As a matter of fact, they are implemented this way. Take a look at the file install_dir/share/mdk/mix-vm-stat.scm if you are curious.)

Scheme scripts
--------------

Another way to use mixguile is to write executable scripts, which perform a set of commands for you. This is done using the mixguile switch -s (being a Guile shell, mixguile accepts all the command options of guile; type mixguile -h for a list of all available command options). For instance, if you have a very useful MIX program foo.mix that you frequently run, you don't have to fire up a MIX virtual machine, load and run the program every time. You can write a Scheme script instead:

     #! /usr/bin/mixguile -s
     !#
     ;;; runprimes: execute the primes.mix program

     ;; load the file you want to run
     (mix-load "../samples/primes")
     ;; execute it
     (mix-run)
     ;; print the contents of registers
     (mix-pall)
     ;; ...

Just save the above script to a file named, say, runtest, make it executable (chmod +x runtest), and execute it from the Unix shell:

     $ ./runtest
     Program loaded. Start address: 3000
     Running ...
     ... done
     Elapsed time: 190908 /Total program time: 190908 (Total uptime: 190908)
     rA: + 30 30 30 30 30 (0511305630)
     rX: + 30 30 32 32 39 (0511313959)
     rJ: + 47 18 (3026)
     rI1: + 00 00 (0000)     rI2: + 55 51 (3571)
     rI3: + 00 19 (0019)     rI4: + 31 51 (2035)
     rI5: + 00 00 (0000)     rI6: + 00 00 (0000)
     Overflow: F
     Cmp: L
     $

Note that this is far more flexible than running programs non-interactively using mixvm (see Non-interactive mode) because you can execute any combination of commands you want from a Scheme script (not just running and dumping the registers). For additional mixguile command line options, see Invoking mixguile.

Using Scheme in mixvm and gmixvm
================================

In the previous section (see Using mixguile) we have seen how the Guile shell mixguile offers you the possibility of using Scheme to manipulate a MIX virtual machine and extend the set of commands offered by mixvm and gmixvm. This possibility is not limited to the mixguile shell. Actually, both mixvm and gmixvm incorporate an embedded Guile interpreter, and can evaluate Scheme expressions. To evaluate a single-line expression at the mixvm or gmixvm command prompt, simply write it and press return (the command parser will recognize it as a Scheme expression because it is parenthesized, and pass it to the Guile interpreter). A sample mixvm session using Scheme expressions could be:

     MIX > load hello
     Program loaded. Start address: 3000
     MIX > (define a (mix-loc))
     MIX > run
     Running ...
     MIXAL HELLO WORLD
     ... done
     Elapsed time: 11 /Total program time: 11 (Total uptime: 11)
     MIX > (mix-pmem a)
     3000: + 46 58 00 19 37 (0786957541)
     MIX > (mix-pmem (mix-loc))
     3002: + 14 09 27 01 13 (0237350989)
     MIX >

You can also load and evaluate a file, using the scmf command like this:

     MIX> scmf /path/to/file/file.scm

Therefore, you have at your disposal all the mixguile goodies described above (new functions, new command definitions, hooks, etc.) inside mixvm and gmixvm. In other words, these programs are extensible using Scheme. See Using mixguile for examples of how to do it.