What is a monitor?

What is a monitor all about? Why do I need one?

Most probably, if you ask this question, you will never need to use the machine language monitor, often referred to as monitor. Nevertheless, I will try to explain it to you. A computer like the C64, but also any modern PC, consists of some parts. Among them are the processor (nowadays, it is most often referred to as Central processing unit, "CPU"), memory, and I/O interfaces. In case of the Commodore 64, the processor is a MOS Technology 6510, a variant of the very popular MOS Technology 6502. This processor contains some registers. These are just some very small data area where the processor essentially can do simple calculations.

The number of registers is very limited. In the case of the 6502/6510, the processor has the following "visible" registers:

  1. one 8 bit accumulator A
  2. two 8 bit index registers X and Y
  3. one 8 bit status register P
  4. one 8 bit stack pointer register S, most often referred to as SP, and
  5. one 16 bit program counter PC.

I assume you are familiar with all this. If not, I recommend you look out for a tutorial on 6502 programming.

The memory of the computer is the place where a program is stored, as well as all of the data is written while the program is running. In case of the Commodore 64, the memory consists of:

  1. 64 KiB of RAM,
  2. 8 KiB of BASIC ROM
  3. 8 KiB of KERNAL ROM
  4. 4 KiB of character ROM which tells the graphics controller how each character on the screen should look like,
  5. 1 KiB of color RAM (to be more precise, this memory only consists of 1024 nibbles),
  6. and some more data areas which I don't want to count here.

Additionally to this, the computer also has some I/O areas which tell parts of the system, like the graphics controller VIC-II, the sound controller SID, or the CIA what they should do. In effect, the I/O devices are the parts of the system that let the user communicate with the system.

Now, to come back to the question: What is a monitor? A machine language monitor program allows the user to look "into" the computer. The user can examine the memory, the processor and the I/O of the computer in order to find out what is happening inside of the machine.

Starting the VICE monitor

Obviously, a monitor is a very helpful piece of software. Now, how do you start it?

I assume you already have VICE running on your system. I tested all of my steps with the Windows version of VICE, WinVICE version 1.21. Nevertheless, the steps can be used with the other ports and other versions of VICE, too. To be more precise, I will always use x64, the Commodore 64 emulator part of VICE.

After starting VICE, you can enter the VICE monitor via File/Monitor, or by pressing Alt+M. Note that the key combination and the menu names can vary on the different versions of VICE. After starting it, a window will open with an output like follows:

** Monitor 000 000
(C:$e5d4)

Note, however, that the exact numbers shown can vary on your machine.

The first line ("** Monitor 000 000") just shows that you just entered the monitor. Additionally, two values are given, which I will not comment now. This will be done in some later part of this series.

The next line (C:$e5d4) is the prompt. That is, the monitor asks you to tell it what you want. In this prompt, there is some information: The "C:" part tells you that you just entered the monitor for the bc/bomputer. Other options would be 8: and 9: for drive 8: and drive 9:, the floppy drives. The value $e5d4 tells you that the emulator would execute the command at address $e5d4 in the computer (C:) as the next command.

In this part of this series on the VICE monitor, we do not want to have a look into the execution. Instead, we just want to examine the contents of the computer. Thus, the above information is not interesting for us (yet).

Getting help on commands

Now, the monitor wants you to tell it what you want to do. It wants to get some command from you. Although you will remember many commands you use frequently, no one is able to remember all of these commands. Thus, you can ask the computer for some help to memory the commands. The command to ask for the list of all commands is called "help". Just enter it (and enter), and you will get the following output:

(C:$e5d4) help

Available commands are:

~                                       >
@                                       a
add_label (al)                          bank
bload (bl)                              block_read (br)
break                                   bsave (bs)
block_write (bw)                        cd
command                                 compare (c)
condition (cond)                        cpu
disass (d)                              delete (del)
delete_label (dl)                       device (dev)
disable                                 dump
enable                                  exit (x)
fill (f)                                goto (g)
help (?)                                hunt (h)
i                                       ignore
io                                      keybuf
load (l)                                load_labels (ll)
mem (m)                                 memchar (mc)
move (t)                                memsprite (ms)
next (n)                                playback (pb)
print (p)                               quit
radix (rad)                             record (rec)
registers (r)                           return (ret)
save (s)                                save_labels (sl)
screen (sc)                             show_labels (shl)
sidefx (sfx)                            step (z)
stop                                    trace (tr)
until (un)                              undump
watch (w)

(C:$e5d4)

This is the list of all available commands. As you can see, some commands just consist of some characters (~, >, @), while others consist of a full name (i.e., save_labels). With many commands, you also have a short form in paranthesis after the full name. This is just for convenience, as you won't want to always write such long names into the window.

If you want to get more precise help, you can use "help" plus the name of the command. For example, to get help on the command "stop", enter "help stop" + enter.

Leaving the VICE monitor

An important command for every command-line based utility like the VICE monitor is the command to exit. As you might have seen in the help output, there is a command exit with abbreviation x:

(C:$e5d4) help exit

Syntax: exit
Abbreviation: x

Leave the monitor and return to execution.

(C:$e5d4)

Thus, if you want to quit the VICE monitor, just enter exit (or just a x) and press enter.

Display memory regions

We want to have a look at the memory. For this, the command "mem" (abbreviation: m) can be used. First of all, let's have a more specific look at the help output on mem:

(C:$e5d4) help mem

Syntax: mem [<data_type>] [<address_opt_range>]
Abbreviation: m

Display the contents of memory.  If no datatype is given, the default
is used.  If only one address is specified, the length of data
displayed is based on the datatype.  If no addresses are given, the
'dot' address is used.

(C:$e5d4)

Note that the same output would be given if you had asked for "help m".

The most important part here seems to be the syntax. It tells you that you have to enter "mem" in order to tell the machine that you want to output memory (of course, you can also use the abbreviation "m"). After this, there are two parts which are optional, that is, you can also ommit them. You see that these are optional because they are surrounded by brackets ([ and ]).

The first optional argument is the data_type. The second optional argument is address_opt_range.

Let's start with the second optional argument, address_opt_range. In fact, this argument consists of two arguments: One address, and another, optional address.

Let's show it with the help of some examples:

  • mem a000 a0ff: This command outputs the memory from address $A000 up to $A0FF. Note: Many monitor program show the memory starting with the first address and ending at the second address, excluding the second address itself. The VICE monitor behaves differently here: It outputs from the first address to the second address, including the second address:
(C:$e5d4) m a000 a100
>C:a000  94 e3 7b e3  43 42 4d 42  41 53 49 43  30 a8 41 a7   ..{.CBMBASIC0.A.
>C:a010  1d ad f7 a8  a4 ab be ab  80 b0 05 ac  a4 a9 9f a8   ................
>C:a020  70 a8 27 a9  1c a8 82 a8  d1 a8 3a a9  2e a8 4a a9   p.'.......:...J.
>C:a030  2c b8 67 e1  55 e1 64 e1  b2 b3 23 b8  7f aa 9f aa   ,.g.U.d...#.....
>C:a040  56 a8 9b a6  5d a6 85 aa  29 e1 bd e1  c6 e1 7a ab   V...]...).....z.
>C:a050  41 a6 39 bc  cc bc 58 bc  10 03 7d b3  9e b3 71 bf   A.9...X...}...q.
>C:a060  97 e0 ea b9  ed bf 64 e2  6b e2 b4 e2  0e e3 0d b8   ......d.k.......
>C:a070  7c b7 65 b4  ad b7 8b b7  ec b6 00 b7  2c b7 37 b7   |.e.........,.7.
>C:a080  79 69 b8 79  52 b8 7b 2a  ba 7b 11 bb  7f 7a bf 50   yi.yR.{*.{...z.P
>C:a090  e8 af 46 e5  af 7d b3 bf  5a d3 ae 64  15 b0 45 4e   ..F..}..Z..d..EN
>C:a0a0  c4 46 4f d2  4e 45 58 d4  44 41 54 c1  49 4e 50 55   .FO.NEX.DAT.INPU
>C:a0b0  54 a3 49 4e  50 55 d4 44  49 cd 52 45  41 c4 4c 45   T.INPU.DI.REA.LE
>C:a0c0  d4 47 4f 54  cf 52 55 ce  49 c6 52 45  53 54 4f 52   .GOT.RU.I.RESTOR
>C:a0d0  c5 47 4f 53  55 c2 52 45  54 55 52 ce  52 45 cd 53   .GOSU.RETUR.RE.S
>C:a0e0  54 4f d0 4f  ce 57 41 49  d4 4c 4f 41  c4 53 41 56   TO.O.WAI.LOA.SAV
>C:a0f0  c5 56 45 52  49 46 d9 44  45 c6 50 4f  4b c5 50 52   .VERIF.DE.POK.PR

How can this output be interpreted? Let's look specifically at the first output line:

>C:a000  94 e3 7b e3  43 42 4d 42  41 53 49 43  30 a8 41 a7   ..{.CBMBASIC0.A.

The first part of the output C:a000 tells you the address where the contents displayed in this output line is located in memory. After this, the bytes follow one by one. Thus, at $A000, there is the byte $94, at $A001, there is the byte $E3, at $A002, there is the byte $7B, and so on. After every 4 byte, the space between two bytes is is a little bit wider, so you can easily count the bytes yourself.

After (in this case) 16 byte, the "new" data ends. What is the last part ..{.CBMBASIC0.A. about? This part repeats the data (thus, the $94, $E3, $7B, $E3, ...). Now, instead of printing each byte with its value, the monitor assumes this to be some text, and outputs the corresponding ASCII (or, more precisely, PETSCII representation of that data. Of course, as ASCII/PETSCII also contains some control characters (for example, there are characters to clear the whole screen), the monitor only prints characters which it consideres as "printable". If not, the monitor just outputs a dot (".").

So, interpreting the line at $A000, you can clearly see the $A004 to $A00C contains the text "CBMBASIC0".

  • mem a000: If you ommit the second parameter, the output will start at $A000. Anyway, the monitor will print up to some point where it thinks it makes sense.
(C:$a101) m a000
>C:a000  94 e3 7b e3  43 42 4d 42  41 53 49 43  30 a8 41 a7   ..{.CBMBASIC0.A.
>C:a010  1d ad f7 a8  a4 ab be ab  80 b0 05 ac  a4 a9 9f a8   ................
>C:a020  70 a8 27 a9  1c a8 82 a8  d1 a8 3a a9  2e a8 4a a9   p.'.......:...J.
>C:a030  2c b8 67 e1  55 e1 64 e1  b2 b3 23 b8  7f aa 9f aa   ,.g.U.d...#.....
>C:a040  56 a8 9b a6  5d a6 85 aa  29 e1 bd e1  c6 e1 7a ab   V...]...).....z.
>C:a050  41 a6 39 bc  cc bc 58 bc  10 03 7d b3  9e b3 71 bf   A.9...X...}...q.
>C:a060  97 e0 ea b9  ed bf 64 e2  6b e2 b4 e2  0e e3 0d b8   ......d.k.......
>C:a070  7c b7 65 b4  ad b7 8b b7  ec b6 00 b7  2c b7 37 b7   |.e.........,.7.
>C:a080  79 69 b8 79  52 b8 7b 2a  ba 7b 11 bb  7f 7a bf 50   yi.yR.{*.{...z.P
>C:a090  e8 af 46 e5  af 7d b3 bf  5a d3 ae 64  15 b0 45 4e   ..F..}..Z..d..EN
>C:a0a0  c4 46 4f d2  4e 45 58 d4  44 41 54 c1  49 4e 50 55   .FO.NEX.DAT.INPU
>C:a0b0  54 a3 49 4e  50 55 d4 44  49 cd 52 45  41 c4 4c 45   T.INPU.DI.REA.LE
>C:a0c0  d4 47 4f 54  cf 52 55 ce  49 c6 52 45  53 54 4f 52   .GOT.RU.I.RESTOR
>C:a0d0  c5 47 4f 53  55 c2 52 45  54 55 52 ce  52 45 cd 53   .GOSU.RETUR.RE.S
>C:a0e0  54 4f d0 4f  ce 57 41 49  d4 4c 4f 41  c4 53 41 56   TO.O.WAI.LOA.SAV
>C:a0f0  c5 56 45 52  49 46 d9 44  45 c6 50 4f  4b c5 50 52   .VERIF.DE.POK.PR
>C:a100  49 4e 54 a3  50 52 49 4e  d4 43 4f 4e  d4 4c 49 53   INT.PRIN.CON.LIS
>C:a110  d4 43 4c d2  43 4d c4 53  59 d3 4f 50  45 ce 43 4c   .CL.CM.SY.OPE.CL
>C:a120  4f 53 c5 47  45 d4 4e 45  d7 54 41 42  a8 54 cf 46   OS.GE.NE.TAB.T.F
>C:a130  ce 53 50 43  a8 54 48 45  ce 4e 4f d4  53 54 45 d0   .SPC.THE.NO.STE.
>C:a140  ab ad aa af  de 41 4e c4  4f d2 be bd  bc 53 47 ce   .....AN.O....SG.
>C:a150  49 4e d4 41  42 d3 55 53  d2 46 52 c5  50 4f d3 53   IN.AB.US.FR.PO.S
>C:a160  51 d2 52 4e  c4 4c 4f c7  45 58 d0 43  4f d3 53 49   Q.RN.LO.EX.CO.SI
>C:a170  ce 54 41 ce  41 54 ce 50  45 45 cb 4c  45 ce 53 54   .TA.AT.PEE.LE.ST
>C:a180  52 a4 56 41  cc 41 53 c3  43 48 52 a4  4c 45 46 54   R.VA.AS.CHR.LEFT
>C:a190  a4 52 49 47  48 54 a4 4d  49 44 a4 47  cf 00 54 4f   .RIGHT.MID.G..TO
>C:a1a0  4f 20 4d 41  4e 59 20 46  49 4c 45 d3  46 49 4c 45   O MANY FILE.FILE
>C:a1b0  20 4f 50 45  ce 46 49 4c  45 20 4e 4f  54 20 4f 50    OPE.FILE NOT OP
>C:a1c0  45 ce 46 49  4c 45 20 4e  4f 54 20 46  4f 55 4e c4   E.FILE NOT FOUN.
>C:a1d0  44 45 56 49  43 45 20 4e  4f 54 20 50  52 45 53 45   DEVICE NOT PRESE
>C:a1e0  4e d4 4e 4f  54 20 49 4e  50 55 54 20  46 49 4c c5   N.NOT INPUT FIL.

You see in this case, that the monitor showed the memory up to $A1EF on my machine. This is because my monitor window is rather large. On a smaller window, it would have choosen a much smaller area.

  • mem: You can also ommit the address entirely. In this case, the monitor will display the contents starting from where it ended in the last command:
(C:$a1f0) m
>C:a1f0  4e 4f 54 20  4f 55 54 50  55 54 20 46  49 4c c5 4d   NOT OUTPUT FIL.M
>C:a200  49 53 53 49  4e 47 20 46  49 4c 45 20  4e 41 4d c5   ISSING FILE NAM.
>C:a210  49 4c 4c 45  47 41 4c 20  44 45 56 49  43 45 20 4e   ILLEGAL DEVICE N
>C:a220  55 4d 42 45  d2 4e 45 58  54 20 57 49  54 48 4f 55   UMBE.NEXT WITHOU
>C:a230  54 20 46 4f  d2 53 59 4e  54 41 d8 52  45 54 55 52   T FO.SYNTA.RETUR
>C:a240  4e 20 57 49  54 48 4f 55  54 20 47 4f  53 55 c2 4f   N WITHOUT GOSU.O
>C:a250  55 54 20 4f  46 20 44 41  54 c1 49 4c  4c 45 47 41   UT OF DAT.ILLEGA
>C:a260  4c 20 51 55  41 4e 54 49  54 d9 4f 56  45 52 46 4c   L QUANTIT.OVERFL
>C:a270  4f d7 4f 55  54 20 4f 46  20 4d 45 4d  4f 52 d9 55   O.OUT OF MEMOR.U
>C:a280  4e 44 45 46  27 44 20 53  54 41 54 45  4d 45 4e d4   NDEF'D STATEMEN.
>C:a290  42 41 44 20  53 55 42 53  43 52 49 50  d4 52 45 44   BAD SUBSCRIP.RED
>C:a2a0  49 4d 27 44  20 41 52 52  41 d9 44 49  56 49 53 49   IM'D ARRA.DIVISI
>C:a2b0  4f 4e 20 42  59 20 5a 45  52 cf 49 4c  4c 45 47 41   ON BY ZER.ILLEGA
>C:a2c0  4c 20 44 49  52 45 43 d4  54 59 50 45  20 4d 49 53   L DIREC.TYPE MIS
>C:a2d0  4d 41 54 43  c8 53 54 52  49 4e 47 20  54 4f 4f 20   MATC.STRING TOO
>C:a2e0  4c 4f 4e c7  46 49 4c 45  20 44 41 54  c1 46 4f 52   LON.FILE DAT.FOR
>C:a2f0  4d 55 4c 41  20 54 4f 4f  20 43 4f 4d  50 4c 45 d8   MULA TOO COMPLE.
>C:a300  43 41 4e 27  54 20 43 4f  4e 54 49 4e  55 c5 55 4e   CAN'T CONTINU.UN
>C:a310  44 45 46 27  44 20 46 55  4e 43 54 49  4f ce 56 45   DEF'D FUNCTIO.VE
>C:a320  52 49 46 d9  4c 4f 41 c4  9e a1 ac a1  b5 a1 c2 a1   RIF.LOA.........
>C:a330  d0 a1 e2 a1  f0 a1 ff a1  10 a2 25 a2  35 a2 3b a2   ..........%.5.;.
>C:a340  4f a2 5a a2  6a a2 72 a2  7f a2 90 a2  9d a2 aa a2   O.Z.j.r.........
>C:a350  ba a2 c8 a2  d5 a2 e4 a2  ed a2 00 a3  0e a3 1e a3   ................
>C:a360  24 a3 83 a3  0d 4f 4b 0d  00 20 20 45  52 52 4f 52   $....OK..  ERROR
>C:a370  00 20 49 4e  20 00 0d 0a  52 45 41 44  59 2e 0d 0a   . IN ...READY...
>C:a380  00 0d 0a 42  52 45 41 4b  00 a0 ba e8  e8 e8 e8 bd   ...BREAK........
>C:a390  01 01 c9 81  d0 21 a5 4a  d0 0a bd 02  01 85 49 bd   .....!.J......I.
>C:a3a0  03 01 85 4a  dd 03 01 d0  07 a5 49 dd  02 01 f0 07   ...J......I.....
>C:a3b0  8a 18 69 12  aa d0 d8 60  20 08 a4 85  31 84 32 38   ..i....` ...1.28
>C:a3c0  a5 5a e5 5f  85 22 a8 a5  5b e5 60 aa  e8 98 f0 23   .Z._."..[.`....#
>C:a3d0  a5 5a 38 e5  22 85 5a b0  03 c6 5b 38  a5 58 e5 22   .Z8.".Z...[8.X."

Now, what is the first parameter about? The help talked about "data_type". In fact, it can be one of D (for decimal), H (for hexadecimal), B (for binary), or O (for octal). Note that this character must be written in upper-case!

Now, lets have a look at some examples again:

  • Decimal (D):
(C:$a3e0) m D a000 a01f
>C:a000 148 227 123 227  67  66  77  66  65  83  73  67   ..{.CBMBASIC
>C:a00c  48 168  65 167  29 173 247 168 164 171 190 171   0.A.........
>C:a018 128 176   5 172 164 169 159 168                   ........
  • Hexadecimal (H):
(C:$a020) m H a000 a01f
>C:a000  94 e3 7b e3  43 42 4d 42  41 53 49 43  30 a8 41 a7   ..{.CBMBASIC0.A.
>C:a010  1d ad f7 a8  a4 ab be ab  80 b0 05 ac  a4 a9 9f a8   ................
  • Octal (O):
(C:$a020) m O a000 a01f
>C:a000 224 343 173 343 103 102 115 102 101 123 111 103   ..{.CBMBASIC
>C:a00c 060 250 101 247 035 255 367 250 244 253 276 253   0.A.........
>C:a018 200 260 005 254 244 251 237 250                   ........
(C:$a020)
  • Binary (B):
(C:$a020) m B a000 a01f
>C:a000 10010100 11100011 01111011 11100011   ..{.
>C:a004 01000011 01000010 01001101 01000010   CBMB
>C:a008 01000001 01010011 01001001 01000011   ASIC
>C:a00c 00110000 10101000 01000001 10100111   0.A.
>C:a010 00011101 10101101 11110111 10101000   ....
>C:a014 10100100 10101011 10111110 10101011   ....
>C:a018 10000000 10110000 00000101 10101100   ....
>C:a01c 10100100 10101001 10011111 10101000   ....

This closes the first part of the series on the VICE monitor. In the next part, we will discuss how you can disassemble parts of the memory.