Classic Computer Magazine Archive COMPUTE! ISSUE 30 / NOVEMBER 1982 / PAGE 172

VIC Micromon

Bill Yee
Winnipeg, Manitoba

VIC machine language programmers: here's one of the most valuable tools there is for working in machine language. Thirty-four commands are at your disposal including single-step, hex conversion, search, EPROM routines, and a relocator. If you aren't yet working with machine language, the instructions for entering and using this program are easy to follow and you might want to add it to your library for later use. Micromon might even lead you into the intriguing and often quite useful world of the machine's own language. As presented, this program takes up 4K of memory from $4000 (16384 decimal) to $4FFF (20479), but there are instructions for locating it elsewhere in RAM memory.

I could not resist F. Arthur Cochrane's suggestion in the January 1982 COMPUTE! about modifying the PET Micromon for VIC use and publishing the results. The VIC Micromon presented here is the product of several months of use and revision of an initial modified version completed in April 1982.

The initial modifications involved redefining Micromon's workspace from the PET tape buffer at $27A to the VIC tape buffer at $33C. The VIC tape buffer was redefined to $375, and the Micromon Load and Save commands rewritten to read and write absolute memory images to cassette tape. A Verify command was added as well.

Other modifications included redefining locations used by Micromon in the BASIC and kernal storage areas from the PET to the VIC equivalents. The address of the decimal output routine used by the conversion commands was changed to the VIC routine at $DDCD. Because the VIC IRQ vector is at $314, rather than at a zero page location such as $90 for the PET, the single instruction interrupt time had to be increased to compensate for the absolute store instructions used. Two of these instructions are used in setting the IRQ vector when rolling out of Micromon for the Walk and Quick trace commands. Also, hardware differences required changes to the interrupt timer addresses. Originally at $E848 and $E849 for the PET, these were redefined as $9128 and $9129 for the VIC.

Micromon uses an IRQ service routine to provide forward and reverse scrolling for the Hex conversion, Memory dump, and Disassembly commands. Because VIC's screen readily relocates and has a unique format of 23 lines by 22 columns, most of the scrolling code in the IRQ service routine had to be rewritten.

Solving Early Problems

I had previously built a 16K memory board for operation in the $2000 to $5FFF address space of the VIC. So, along with the modifications already mentioned, the programming for the initial VIC Micromon included a relocation from $1000 to $4000. The code was entered as two separate 2K blocks on my VIC using a BASIC Hex Editor and subsequently programmed onto two 2716 EPROMs with a programmer I had built to operate off the VIC USER I/O port. An extension of the BASIC Hex Editor provided the EPROM programming control.

Once installed on my VIC at $4000, VIC Micromon was accessed by a SYS16384 from BASIC. Each Micromon command was exercised for proper operation. I had difficulty returning to BASIC with the E and X commands, as well as stack interference in executing test programs with the G, W, and Q commands. I solved these problems by changing the stack area used by VIC Micromon to the bottom half of the $100 page. This was done by setting the stack pointer to $7F rather than $FF in the command input section of VIC Micromon.

The New locater command would work only once in the word mode when the command was invoked several times consecutively. A flag at $28C for PET Micromon and $34E for VIC Micromon differentiates between the instruction mode and the word mode in the New locater command. The problem is due to the flag being used also as an offset index to check absolute addresses. The flag was being incremented without being cleared on each consecutive New locater command in word mode. This was fixed by inserting code in the command input section of VIC Micromon to always clear $34E prior to execution of any command.

The Assembler command would not properly assemble branch instructions which had branch offsets of $7E and $7F. This problem resulted from a simple plus/minus range check prior to adjusting the offset value by -2. The fix for VIC Micromon is given here as an inline patch for PET Micromon users. The PET Micromon code from $1525 to $1538 was rewritten to use a value of $82 for a range check. The resulting code, which is one byte longer, was accommodated by replacing the branch and jump instructions at $150E to $1512 with two NOPs and a branch. The code at $1513 to $1524 was moved down one location to be at $1512 to $1523, and the branch instructions originally at $1519 and $1520 had their offsets adjusted up by one.

Table 1: Micromon Locations Redefined for VIC
Location Old Value New Value Location Old Value New Value
150E F0 EA 1523 13 11
150F 03 EA 1524 11 90
1510 4C D0 1525 90 01
1511 91 7F 1526 0A 88
1512 15 20 1527 98 C8
1513 20 3C 1528 D0 D0
1514 3C 18 1529 6F 6F
1515 18 AC 152A AE 98
1516 AC 8B 152B 91 2A
1517 8B 02 152C 02 AE
1518 02 F0 152D 30 91
1519 F0 2F 152E 6A 02
151A 2E AD 152F 10 E0
151B AD 93 1530 08 82
151C 93 02 1531 C8 A8
151D 02 C9 1532 D0 D0
151E C9 9D 1533 65 03
151F 9D D0 1534 AE B0
1520 D0 20 1535 91 03
1521 1F 20 1536 02 38
1522 20 13 1537 10 B0

F. Arthur Cochrane presented an extra set of commands implemented on about an additional 1K module called Micromon Plus. Of the commands in Micromon Plus, I felt that the Print switcher and PROM programmer commands would be desirable in VIC Micromon. However, instead of creating an extra module above the existing 4K of the initial VIC Micromon, I decided that, with some code crunching, the Print switcher and PROM programmer commands could be contained within an enhanced 4K VIC Micromon. Since there are many printers available with a RS-232 interface, the enhanced VIC Micromon Print switcher command would support the RS-232 interface on the VIC User I/O port rather than the VIC serial port interface. Also, since I already had an EPROM programmer working off the User I/O port, the enhanced VIC Micromon PROM programmer command would support my programmer rather than one on the IEEE bus.

Memory Saving

Code crunching consisted of code optimization and code removal while keeping function and structure. The table of internal Micromon addresses used to set up and check interrupt vectors was removed. While the table helped in any relocation of Micromon, I felt that direct changes of vector address values were relatively easy and well worth the program area saved. VIC Micromon has six locations with interrupt vector values that must be changed when VIC Micromon is relocated. The checks for the different versions of PET BASIC were removed as well. It didn't make sense to have universality in some parts of VIC Micromon when a good part was applicable only to the VIC.

The VIC has two levels of indirection for the input and output to device routines. The first level is the use of PET compatible addresses for the jump vectors at the end of the 8K kernal ROM. The second level of indirection is the use of an indirect jump table in RAM which allows the user to redefine the vectors. Because of this, I felt that the use of I/O jump vectors at the beginning of Micromon was unnecessary.

Besides the four ROM routines mentioned by F. Arthur Cochrane (input character, output a character, load a program, and save a program), there were other ROM routines, such as get from keyboard ($FFE4) and close I/P and O/P channels ($FFCC), used by PET Micromon. For VIC Micromon these were expanded to about 20 ROM routines, since I chose to use VIC kernal routines when possible. For example, the test for STOP key code at location $18AE of the PET Micromon was replaced with a call to the test STOP key routine at $FFE1 in the VIC kernal ROM.

Altogether, the code crunching resulted in over 250 bytes freed. This allowed me to add the Print switcher and EPROM commands along with a few handy ones which did not require much code to implement. Following is a detailed description of VIC Micromon commands with a different format or function from similar commands in PET Micromon and of new commands in VIC Micromon.

VIC Micromon Instructions

Initialize Memory And Screen Pointers

.1 1000 1E00 1E

Define low memory as $1000 and high memory as $1E00 regardless of the memory present. The screen is defined to start at the $1E page of memory. The screen memory should always be on an even page within the range of $1000 to $1E00. Odd page values result in incorrect setup and operation of the VIC display. Although 3K of RAM can be added at $400 to $FFF, this memory is not accessible for use as screen memory.

Memory pages at $000 and $200 are accessible, but are not usable since they are used for BASIC and kernal storage, working buffers, and stack area. If the screen page is within the low to high memory range specified, there can be usage conflict of the screen memory pages. If the "I" command is used and exit is made to BASIC, the NEW command must be invoked in the BASIC environment to clean up the memory pointers used by BASIC.

Jump To Micromon Subroutine

.J 2000

The subroutine at $2000 is called while remaining in the VIC Micromon environment. The assembly language subroutine should exit by using a RTS instruction, which causes a return to the command input section of VIC Micromon. The machine image as shown by the Register display command is not used, nor is it disturbed when the subroutine returns to VIC Micromon.

Load

.L 2000 "TEST FILE" 01

Search for and, if found, load into memory the data file on device # 1 named TEST FILE. If the name is not specified, the first file found is loaded. The data is loaded into memory starting at location $2000. The last address loaded is determined by the length of the binary data file. If the device number is not specified, it defaults to device # 1, which is the VIC cassette tape. The original memory addresses and name of the last file read can be inspected by doing a Memory display of the tape buffer which is at $375 for VIC Micromon.

Print Switcher

.P

If the output is to the screen, then switch the output to the RS-232 channel (device # 2). If the output is not to the screen, restore the output to the screen with the RS-232 channel left active until the RS-232 output buffer is drained. Note that opening the RS-232 channel grabs 512 bytes for I/O buffering from the top of memory.

.P 0000

Regardless of the output, clear the RS-232 channel and set output to the screen.

.P CCBB

If the output is to the screen, set CC into the RS-232 command register at location $294 and BB into the RS-232 control register at location $293. Output is then switched to the RS-232 channel. This command is invalid if output is not currently to the screen.

Command Register Format

Field Use Value Description
7,6,5 Parity Options --0 Parity disabled
001 Odd parity
011 Even parity
101 Mark transmitted
111 Space transmitted
4 Duplex 0 Full duplex
1 Half duplex
3,2,1 Unused
0 Handshake 0 3line
1 xline

Control Register Format

Field Use Value Description
7 Stop Bits 0 1 stop bit
6,5 Word Length 00 8bits
01 7bits
10 6bits
11 5bits
4 Unused
3,2,1,0 Baud Rate 0000 User rate
0001 50 Baud
0010 75
0011 110
0100 134.5
1000 1200
1001 1800
1010 2400

Save

.S 2000 3000 "TEST FILE" 01

Save memory from $2000 up to, but not including, $3000 onto device # 1, which is the VIC cassette tape. If the device number is not specified, it defaults to device # 1. The name TEST FILE is placed in the file header for the file saved.

Verify

.V 2000 "TEST FILE" 01

Search for and verify, if found, the data file on device #1 named "TEST FILE." If the name is not specified, the first file found is verified. The data is verified by reading the file and comparing it to the data in memory starting at location $2000. If not specified, the device defaults to device #1. If there is a mismatch, the message ERROR is outputted to the screen at the end of the file verification.

Command End Tone

.(

Enable the command end tone. A continuous tone will be generated at the end of execution of the next command. The tone can be turned off but still be enabled by just hitting the carriage return. No tone is generated if there is a syntax error while inputting the next command.

.)

Disable the command end tone.

Program EPROM

.π 2800 2FFF 00

Program the 2716 type EPROM via the EPROM programmer on the VIC User I/O port with data read from memory starting at location $2800 and ending at location $2FFF. The last input parameter specifies in hex the starting 256 byte page offset on the EPROM. If the low order byte of the starting memory address is zero and the offset is zero, then the programming starts with the first byte of the EPROM. For example, to program only the last byte of the 2K EPROM with a data byte from location $2FFF in memory, the command would be:

.π 2FFF 2FFF 07

During programming, a compare of EPROM to memory is done for each data byte just after it is written to the EPROM. Any mismatch due to failure to program the EPROM results in output to the screen of the mismatched memory location. If programming must be terminated early, just hit the STOP key. No other means should be used to abort EPROM programming. A warm restart or power down while programming can damage the EPROM.

Read EPROM

.£ 2999 27FF 00

Load memory starting at location $2000 and ending at location $27FF with data read from the EPROM via the EPROM programmer on the VIC User I/O port. The last input parameter specifies in hex the starting 256 byte page offset on the EPROM. If the low order byte of the starting memory address is zero and the offset is zero, then the reading starts with the first byte of the EPROM. For example, to read only the last byte of the 2K EPROM and compare that with the data byte in memory at location $37FF, the command would be:

.£ 10FF 10FF 07

During memory load, a compare of EPROM to memory is done for each data byte just after it is written to memory. Any mismatch because of failure to write the memory with data from the EPROM results in output to the screen of the mismatched memory location. The STOP key can be used to terminate the command early.

Compare EPROM

.=3000 37FF 00

Compare memory starting at location $3000 and ending at location $37FF with data read from the EPROM via the EPROM programmer on the VIC User I/O port. The last input parameter specifies in hex the starting 256 byte page offset on the EPROM. If the low order byte of the starting memory address is zero and the offset is zero, then the reading starts with the first byte of the EPROM. For example, to read only the last byte of the 2K EPROM and compare that with the data byte in memory at location $37FF, the command would be:

.=37FF 37FF 07

Any mismatch between the EPROM and corresponding memory data results in output to the screen of the mismatched memory location. The STOP key can be used to terminate the command early.

Table 2: Commands for VIC Micromon

VIC Micromon Instruction Command
SIMPLE ASSEMBLER A
BREAK SET B
COMPARE MEMORY C
DISASSEMBLER D
EXIT VIC MICROMON E
FILL MEMORY F
GO RUN G
HUNT MEMOYR H
INTIAL MEMORY &SCREEN PTRS I
JUMP TO SUBROUTINE J
LOAD MEMORY FROM DEVICE L
MEMORY DISPLAY M
NEW LOCATER N
OFFSET OR BRANCH CALCULATE O
PRINT SWITHCER P
QUICK TRACE Q
REGISTER DISPLAY R
SAVE MEMORY TO DEVICE S
TRANSFER MEMORY T
VERIFY MEMORY FROM DEVICE V
WALK COAD W
EXIT TO BASIC X
ASCII CONVERSION "
DECIMAL CONVERSION #
HEXADECIMAL CONVERSION $
BINARY CONVERSION %
CHECKSUM MEMORY &
COMMAND END TONE ENABLE (
COMMAND END TONE DISABLE )
ADDITON +
SUBTRACTION -
LOAD MEMORY FROM EPROM £
PROGRAMERPROM FORM MEMORY π
COMPARE EPROM TO MEMORY =

Of the set of commands available on the PET version of Micromon, only two were removed in the conversion to the VIC. These were the K (Kill Micromon) and Z (change character sets) commands. The K command is not necessary since the VIC doesn't have the TIM monitor. The function of the Z command, which is to change character sets, is already provided for on the VIC by pressing the VIC shift and Commodore keys at the same time. The rest of the commands described by F. Arthur Cochrane for the PET Micromon (see COMPUTE!, January 1982, p. 160) all apply identically to the commands for VIC Micromon, with the exception of the LOAD and SAVE commands, which have different formats.

VIC Micromon is always entered from VIC BASIC by a SYS 16384 when it resides at $4000 to $4FFF. Either the E (Exit VIC Micromon) or the X (Exit to BASIC) command would be used to exit VIC Micromon and return to the BASIC environment. The difference between these two commands is that the X command leaves the VIC Micromon vectors in the IRQ and BRK interrupt vector locations while in the BASIC environment. Also, the tape buffer is left defined as beginning at $375. Thus, certain IRQ interrupt conditions such as the moving of the cursor to the top or bottom of the screen with output from a D, M, or $ command displayed will cause scrolling and reentry into VIC Micromon. Also, if a BRK instruction is executed, VIC Micromon will be reentered via its BRK interrupt handler.

The E command restores the IRQ and BRK interrupt vectors and resets the tape buffer pointer to a value of $33C prior to exit to the VIC BASIC environment. Thus all active linkages and vectors to VIC Micromon are removed, and the VIC behaves as if VIC Micromon never existed. In particular, the E command should be used to exit VIC Micromon when the normal VIC cassette tape LOAD, SAVE, and VERIFY commands are to be used in the BASIC environment. Otherwise, invalid results are likely to occur with some tape operations.

Both the E and X commands expect the stack pointer value (as shown for SP by the Register display command) to be the same as when VIC Micromon was first entered via the BASIC SYS command. If the value of SP or the part of the stack pointed to by SP is overwritten, such as by the execution of faulty code, a clean exit to BASIC by the E and X commands is unlikely. However, both the E and X commands do check if BASIC has been initialized, and if not, exit to BASIC is via an indirect jump to the address given at location $C000. The address given in location $C000 is $E378, which is the entry to initialize BASIC. In this case, the value of SP and the contents of the stack aren't important. Once in BASIC and regardless of how the exit from VIC Micromon was made, any subsequent access to VIC Micromon at $4000 is always by a SYS16384.

VIC Micromon as given here is located from $4000 to $4FFF. It can be relocated to any 256 byte page boundary by making the changes, as shown in the following example, which relocate VIC Micromon from $4000 to $6000.

The example begins with VIC Micromon at $4000 and ends with a relocated VIC Micromon in RAM at $6000 as well as the original at $4000.

.T 4000 4FFF 6000
.N 6000 6003 2000 4000 4FFF
.N 6012 6E6D 2000 4000 4FFF
.N 6FB5 6FFE 2000 4000 4FFF W
Location Old Value New Value
6081 45 65
602A 43 63
6392 4C 6C
6650 45 65
66E7 45 65
6897 43 63

In order to access the relocated VIC Micromon at $6000, exit using the E command and then from BASIC use SYS24576.

Cartridge And Checksum

The VIC-20 treats cartridge programs located at $A000 in a special way. On power-up, a test is made for the existence of the $A000 cartridge program, and if one exists, an indirect jump is made to the address specified at location $A000. This jump is made after the stack pointer is initialized, but before anything else is done. Because kernal initialization has not occurred, any cartridge program using kernal I/O routines must do kernal initialization before using those routines.

VIC Micromon as presented here has the kernal initialization calls built in so that it can easily be relocated and used as a cartridge program at $A000. Besides making the changes to relocate it to $A000, the only additional changes are to the first four bytes of VIC Micromon.

Location Contents
A000 09
A001 A0
A002 C7
A003 FE

Power-up with VIC Micromon installed as a cartridge at $A000 will result in immediate entry into VIC Micromon. Because BASIC is not initialized when the E or X command is used after power-up, the exit to BASIC will be via an indirect jump to the address given in location $C000, which is the entry to initialization of BASIC. Once in BASIC, subsequent access of VIC Micromon at $A000 must be made to location $A012, which is done via a SYS40978.

There is one last point, or rather one last byte, in VIC Micromon which is not used for anything other than to make the 4K byte checksum of VIC Micromon come out to a rounded up page value. For example, the VIC Micromon from $4000 to $4FFF has a data byte value of $E6 at location $4FFF that results in a checksum of $BF00. This provides an easy way to verify the integrity of VIC Micromon without having to memorize or look up a checksum.

Three Notes On VIC Micromon

Using the VIC Micromon tape commands L, S, and V on a VIC-20 with 3K of RAM installed at $400 to $FFF will result in overwrite of $400 to $438 with file header characters (blanks). This is due to the tape buffer being relocated to $375 while in VIC Micromon from the normal $33C. The normal VIC cassette commands will work properly and not overwrite this area when you EXIT from VIC Micromon. This is because VIC Micromon restores the tape buffer pointer value to $33C when an EXIT is done. This problem does not occur if the 3K RAM at $400 to $FFF is not installed.

If the I (Initialize memory and screen pointers) command was used in VIC Micromon and you EXIT, then the RUN/STOP plus RESTORE should be used in addition to the NEW command to clean up the BASIC environment.

Any binary image saved on cassette tape with the VIC Micromon "S" command can be loaded in the normal VIC-20 BASIC environment by using the command: LOAD" ", 1, 1 which looks for the next program on tape and LOADs it into the same part of memory that it came from (see page 9 of VIC-20 Programmer's Reference Guide).

Checksum

There's a good amount of typing to do to enter the VIC Micromon program. Use the following BASIC program (after you've SAVEd a copy of your efforts) to locate any errors you might have made.

Program 3: VIC Micromon Checksum

10 DATA 12915, 16867, 15061, 13732, 14507, 13829, 13801, 12813, 15027, 13920
20 DATA 14355, 11977, 11877, 13583, 11338, 15173, 12337, 14852, 14051, 15723
30 DATA 13442, 14047, 14746, 15059, 13134, 15848, 15858, 17856, 13327, 8655
40 DATA 12171, 10231
100 Q = 16384
110 FOR BLOCK = 1 TO 32
120 FOR BYTE = 0 TO 127
130 X = PEEK (Q + BYTE) : CK = CK + X
140 NEXT BYTE
150 READSUM
160 IF SUM < > CK THEN PRINT " ERROR IN BLOCK #" : GOTO 170
175 PRINT "			BLOCK"BLOCK" IS CORRECT "
170 CK = 0 : Q = Q + 128
180 NEXT BLOCK