summaryrefslogtreecommitdiffhomepage
path: root/doc/mdk_gstart.texi
blob: b35fea7709b3900227a5bd1b93462046723112c9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
@c -*-texinfo-*-
@c This is part of the GNU MDK Reference Manual.
@c Copyright (C) 2000, 2001
@c   Free Software Foundation, Inc.
@c See the file mdk.texi for copying conditions.

@c $Id: mdk_gstart.texi,v 1.6 2001/09/13 00:13:39 jao Exp $

@node Getting started, mixvm.el, MIX and MIXAL tutorial, Top
@chapter Getting started
@cindex tutorial

In this chapter, you will find a sample code-compile-run-debug session
using the @sc{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 @ref{MIX and MIXAL tutorial}. 

@menu
* Writing a source file::       A sample MIXAL source file.
* Compiling::                   Using @code{mixasm} to compile source
                                files into binary format.
* Running the program::         Running and debugging your programs.
* Using mixguile::              Using the Scheme interpreter to run and
                                debug your programs.
@end menu

@node Writing a source file, Compiling, Getting started, Getting started
@section Writing a source file
@cindex MIXAL
@cindex source file
@cindex .mixal file

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

@example
*                                                        (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)
@end example
         
@noindent MIXAL source files should have the extension @file{.mixal}
when used with the @sc{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 whitespace characters (blanks and or
tabs). While Knuth's definition of MIXAL each field must start at a
fixed pre-defined column number, the @sc{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:

@itemize @minus
@item
an optional label, which either refers to the current memory address (as
@code{START} and @code{MSG} in lines 7 and 9) or a defined symbol
(@code{TERM}) (if present, the label must always start at the first
column in its line, for the first whitespace in the line maks the
beginning of the second field),
@item
an operation mnemonic, which can represent either a MIX instruction
(@code{OUT} and @code{HLT} in lines 6 and 7 above), or an assembly
pseudoinstruction.
@item
an optional operand for the (pseudo)instruction, and
@item
an optional free text comment.
@end itemize

@noindent Lines 9-12 of the @file{hello.mixal} file above also show the
second (and last) difference between Knuth's MIXAL definition and ours:
the operand of the @code{ALF} pseudoinstruction (a word of five
characters) must be quoted with using ""@footnote{In Knuth's definition,
the operand always starts at a fixed column number, and the use of
quotation is therefore unnecessary. As @code{mixasm} releases this
requirement, marking the beginning and end of the @code{ALF} operand
disambiguates the parser's recognition of this operand when it includes
blanks}. 

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

@node Compiling, Running the program, Writing a source file, Getting started
@section Compiling
@cindex compiling
@cindex binary programs
@cindex virtual machine
@cindex assembler
@cindex @code{mixasm}

Three simulators of the MIX computer, called @code{mixvm}, @code{gmixvm}
and @code{mixguile}, are included in the @sc{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 @code{mixasm}, the MIXAL assembler. So, in order to compile
the @file{hello.mixal} file, you can type the following command at your
shell prompt:

@example
mixasm -g hello @key{RET}
@end example

@cindex .mix file

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


@node Running the program, Using mixguile, Compiling, Getting started
@section Running the program
@cindex @code{mixvm}
@cindex non-interactive mode
@cindex interactive mode

MIX is a mythical computer, so it is no use ordering it from your
favorite hardware provider. @sc{mdk} provides three software simulators of
the computer, though. They are

@itemize @bullet
@item
@code{mixvm}, a command line oriented simulator,
@item
@code{gmixvm}, a GTK based graphical interface to @code{mixvm}, and
@item
@code{mixguile}, a Guile shell with a built-in MIX simulator.
@end itemize

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

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

@menu
* Non-interactive mode::        Running your programs non-interactively.
* Interactive mode::            Running programs interactively.
* Debugging::                   Commands for debugging your programs.
@end menu

@node Non-interactive mode, Interactive mode, Running the program, Running the program
@comment  node-name,  next,  previous,  up
@subsection Non-interactive mode
@cindex non-interactive mode

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

@example
mixvm -r hello @key{RET}
@end example

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

@example
MIXAL HELLO WORLD
** Execution time: 11
@end example

@noindent Since our hello world program uses MIX's device number 19 as
its output device (@pxref{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.), @code{mixvm} would
have created a file named after the device used (e.g. @file{disk4.dev})
and written its output there@footnote{The device files are stored, by
default, in a directory called @file{.mdk}, which is created in your
home directory the first time @code{mixvm} is run. You can change this
default directory using the command @code{devdir} when running
@code{mixvm} in interactive mode (@pxref{Configuration commands})}. Note
also that the virtual machine reports the execution time of the program,
according to the (virtual) time spent in each of the binary instructions
(@pxref{Execution times}).

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

@example
mixvm -d -r hello
@end example

@noindent you will obtain the following output:

@example
MIXAL HELLO WORLD
** Execution time: 11
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
@end example

@noindent 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, not
to mention stepping through your program's instructions or setting
breakpoints. Enter interactive mode.

@node Interactive mode, Debugging, Non-interactive mode, Running the program
@comment  node-name,  next,  previous,  up
@subsection Interactive mode
@cindex interactive mode

To enter the MIX virtual machine interactive mode, simply type

@example
mixvm @key{RET}
@end example

@noindent at your shell command prompt. This command enters the
@code{mixvm} command shell. You will be presented the following command
prompt:

@example
MIX >
@end example

@noindent The virtual machine is initialised and ready to accept your
commands. The @code{mixvm} command shell uses GNU's readline, so that
you have at your disposal command completion (using @key{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 @ref{Command Line
Editing,,,Readline}.)

@cindex @code{load}
Usually, the first thing you will want to do is loading a compiled MIX
program into memory. This is acomplished by the @code{load} command,
which takes as an argument the name of the @file{.mix} file to be
loaded. Thus, typing

@example
MIX > load hello @key{RET}
Program loaded. Start address: 3000
MIX >
@end example

@noindent will load @file{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
@code{pc}:

@cindex @code{pc}
@example
MIX > pc
Current address: 3000
MIX >
@end example

@cindex @code{run}
After loading it, you are ready to run the program, using, as you surely
have guessed, the @code{run} command:

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

@noindent 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)@footnote{Printing of timing statistics can be disabled using
the command @code{timing} (@pxref{Configuration commands}).}. After
running the program, the program counter will point to the address after
the one containing the @code{HLT} instruction. In our case, asking the
value of the program counter after executing the program will give us

@example
MIX > pc
Current address: 3002
MIX >
@end example

@cindex @code{pmem}
@noindent You can check the contents of a memory cell giving its address
as an argument of the command @code{pmem}, like this

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

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

@example
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 >
@end example

@cindex @code{preg}
@noindent
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

@example
MIX > preg A
rA: + 00 00 00 00 00 (0000000000)
MIX >
@end example

@cindex @code{help}
@noindent
Use the comand @code{help} to obtain a list of all available commands,
and @code{help COMMAND} for help on a specific command, e.g.

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

@noindent
For a complete list of commands available at the MIX propmt,
@xref{mixvm}. In the following subsection, you will find a quick tour
over commands useful for debugging your programs.

@node Debugging,  , Interactive mode, Running the program
@comment  node-name,  next,  previous,  up
@subsection Debugging commands

@cindex @code{next}
The interactive mode of @code{mixvm} lets you step by step execution of
programs as well as breakpoint setting. Use @code{next} to step through
the program, running its instructions one by one. To run our
two-instruction @file{hello.mix} sample you can do the following:

@example
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 > @end example
@noindent
(As an aside, the above sample also shows how the virtual machine
handles cummulative time statistics and automatic program restart).

@cindex @code{sbpa}
@cindex breakpoints

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

@example
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 >
@end example

@cindex @code{sbp}
@cindex breakpoints
@noindent
Note that, since we compiled @file{hello.mixal} with debug info enabled
(the @code{-g} flag of @code{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 @code{sbp LINE_NO}, e.g.

@example
MIX > sbp 4
Breakpoint set at line 7
MIX > 
@end example

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

@cindex @code{psym}
MIXAL lets you define symbolic constants, either using the @code{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 @code{psym} command. For our hello world sample, you
will obtain the following output:

@example
MIX > psym
START:  3000
TERM:  19
MSG:  3002
MIX > 
@end example

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

@node Using mixguile,  , Running the program, Getting started
@section Using @code{mixguile}

With @code{mixguile} you can run a MIX simulator embedded in a Guile
shell, that is, using Scheme functions and programs. As with
@code{mixvm}, @code{mixguile} can be run both in interactive and
non-interactive modes. The following subsections provide a quick tour on
using this MIX emulator.

@menu
* The mixguile shell::          
* Additional functions::        
* Defining new functions::      
@end menu

@node The mixguile shell, Additional functions, Using mixguile, Using mixguile
@subsection The @code{mixguile} shell
@cindex Scheme
@cindex @code{mixguile}
@cindex REPL

If you simply type

@example
mixguile @key{RET}
@end example
@noindent
at the command prompt, you'll be presented a Guile shell prompt like
this

@example
guile>
@end example
@noindent
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 @code{mixvm}
commands described in the previous sections (and in @pxref{mixvm}) have
a Scheme function counterpart named after it by prepending the prefix
@code{mix-} to its name. Thus, to load our hello world program, you can
simply enter

@example
guile> (mix-load "hello")
Program loaded. Start address: 3000
guile> 
@end example
@noindent
and run it using @code{mix-run}:

@example
guile> (mix-run)
Running ...
MIXAL HELLO WORLD                                                     
... done
Elapsed time: 11 /Total program time: 11 (Total uptime: 11)
guile> 
@end example
@noindent
In the same way, you can execute it step by step using the Scheme
function @code{mix-next} or set a breakpoint:

@example
guile> (mix-sbp 4)
Breakpoint set at line 5
guile> 
@end example
@noindent
or, if you one to peek at a register contents:

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

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

@node Additional functions, Defining new functions, The mixguile shell, Using mixguile
@subsection Additional MIX Scheme functions

@node Defining new functions,  , Additional functions, Using mixguile
@subsection Definining new functions
@cindex Scheme functions

Scheme is a powerful language, and you can use it inside @code{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, finally, shows the registers contents, all in one shot:

@example
guile> (define my-load-and-run  @key{RET}
         (lambda (file)   @key{RET}
           (mix-load file)   @key{RET}
           (display "File loaded: ")   @key{RET}
           (mix-pprog)   @key{RET}
           (mix-run)   @key{RET}
           (mix-preg)))   @key{RET}
guile> 
@end example
@noindent
and use it to run your programs:

@example
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> 
@end example


Or, maybe, you want a function which sets a breakpoint at a specified
line number before executing it:

@example
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>
@end example

As you can see, the possibilities are virtually unlimited. Of course,
you don't need to type a function definition each time you start
@code{mixguile}. You can write it in a file, and load it using Scheme's
@code{load} function. For instance, you can create a file named, say,
@file{functions.scm} with the contents:

@example
(define my-load-and-run-with-bp
  (lambda (file line)
    (mix-load file)
    (mix-sbp line)
    (mix-run)))
@end example

and load it at the @code{mixguile} prompt:

@example
guile> (load "functions.scm")
@end example



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: