Extending WozMon

Using, learning, programming and modding the Gigatron and anything related.
Forum rules
Be nice. No drama.
Post Reply
monsonite
Posts: 101
Joined: 17 May 2018, 07:17

Extending WozMon

Post by monsonite »

Last June, Marcel ported the classic 1976 Apple 1 monitor program "WozMon" to Gigatron - and with this new tool in place, Tiny BASIC followed on very shorty afterwards. Just this week, WozMon has allowed the
debugging of the expansion pcb - without the need for any external resources - untethered to a PC.

Back in 1976, RAM was a limited resource - and so WozMon was tailored to just under 256 bytes - so that it would fit in the RAM available - and leave space for the User's program. Gigatron does not suffer such acute RAM limitations, and so Marcel has allowed the ported version of WozMon to grow to about 600 bytes - in order to allow for printing character routines and other improvements to the original.

I tinkered with WozMon this evening - following a couple of the given examples, and it occurred to me that WozMon provides a simple interactive environment that allows code snippets to be tested - without the clutter or distraction of other processes running in the background.

WozMon has a few useful routines that can be exploited by the User, mostly those involved with printing characters and displaying the RAM contents as hexadecimal digits on the screen. WozMon also allows small assembly language programs to be run and tested in isolation - using the R (Run) command.

What if we were to extend WozMon, with a whole suite of new commands, with the aim of adding many new features and making it a lot more interactive? Most of the hard work is already done, new commands could be added in the form of a simple jump table that allows access to further blocks of code. By stringing these command together, you can mechanise the process of executing a series of assembler routines.

Tiny BASIC gives access to the RAM through its PEEK POKE and USR keywords. However, Tiny BASIC carries a lot of baggage, as it needs to interpret every line of code - again and again in every loop. What I am proposing is a means of chaining together vasm routines, using a command interpreter that lies somewhere between WozMon and Tiny BASIC - in terms of codespace and complexity.

My dreams are inspired by those of Chuck Moore - who in early 1968 sat down alone with an IBM 1130 and created his own interactive programming environment. It included a self hosted assembler and disk routines. With the recent developments with the expansion pcb - it looks like Gigatron will acquire some mass storage and the means to save to and load from a non-volatile memory. This could be a uSD card or even a FRAM (ferroelectric RAM) accessed via the SPI bus. It looks like Gigatron could just leapfrog the whole magnetic storage phase of development.

Provided that I can disassemble WozMon sufficiently to understand its flow and operation, I think I can write some useful extensions.
User avatar
marcelk
Posts: 488
Joined: 13 May 2018, 08:26

Re: Extending WozMon

Post by marcelk »

I'm thrilled about the idea, please go for it.... I have these lingering thoughts about improving GCL, but GCL is/was really a bootstrapping thing in the first place. I don't want to spend time on tweaking it while other areas are lacking more. It just works "ok", for -me-. To compensate for its strangeness, I documented HelloWorld.gcl, WozMon.gcl and TinyBASIC.gcl a lot better than any of the other GCL stuff. But honestly, it would be a much better idea to work towards a standard FORTH (for example) instead of working on an interactive GCL prompt. Simply because of the familiarity, existing documentation and tutorials.

Doing interactive stuff in WozMon is thrilling but it has its limits. I could never memorize most of the 6502 opcodes, and I even forget the vCPU opcodes within hours after using them (except RET = 0xFF). In this interview Bill Atkinson tells an amazing story on how Woz coded: https://youtu.be/6tUWoy1tJkE?t=2899. I can't wrap my head around that.

While I miss the monitor programs I was used to, I don't miss pegging code to fixed addresses too much. But as a first step, just a vCPU disassembler extension to WozMon would be super useful.

BTW: In case SDcard and FAT support materialise this year (still hard to tell), the world will change anyway. From there we can seriously start to think about a DOS, a shell and multithreading. And about different machine languages per thread (vCPU, 6502, Z80, ...). The quickest way to have the Gigatron play chess is to implement 6502 compatibility so it can run the KIM-1's Microchess.
monsonite
Posts: 101
Joined: 17 May 2018, 07:17

Re: Extending WozMon

Post by monsonite »

I have started to look at extending WozMon with a disassembler mode.

This is mainly a learning exercise to familiarise me with vasm, but be a useful new feature in its own right.

vasm is a fairly simple language to disassemble - because most of the instructions are only 2 bytes. (Compare this with Z80!!!)

This means that the rules of dissassembly can be greatly simplified.

vasm only has 37 opcodes, and looking at the frequency of use in typical vasm programs such as WozMon and Tiny BASIC - there are a handful of instructions that are used very frequently, and a few that are used very seldom or not at all.

65% of all instructions are conveyed in just 8 opcodes.

This greatly simplifies the task of decoding the opcodes and printing the mnemonics as a disassembly listing.
User avatar
marcelk
Posts: 488
Joined: 13 May 2018, 08:26

Re: Extending WozMon

Post by marcelk »

There shouldn't be any unused instructions in vCPU's overpacked primary code page. The vCPU instruction count is 34, 39 or 40, depending on how you treat BCC, aka Branch Condition Code (not to be confused with Branch Carry Clear on systems with a carry flag). BCC gets followed by a second opcode for the condition: one of EQ, NE, LT, GT, GE, LE. These six have no meaning on their own.

I updated the vCPU instruction table in GCL-language.txt:

Code: Select all

Mnem. Operands Description
----- -------- -----------
ST    $DD      Store byte in zero page ([D]=vAC&256)
STW   $DD      Store word in zero page ([D],[D+1]=vAC&255,vAC>>8)
STLW  $DD      Store word in stack frame ([vSP+D],[vSP+D+1]=vAC&255,vAC>>8)
LD    $DD      Load byte from zero page (vAC=[D])
LDI   $DD      Load immediate small positive constant (vAC=D)
LDWI  $DDDD    Load immediate word constant (vAC=D)
LDW   $DD      Word load from zero page (vAC=[D]+256*[D+1])
LDLW  $DD      Load word from stack frame (vAC=[vSP+D]+256*[vSP+D+1])
ADDW  $DD      Word addition with zero page (vAC+=[D]+256*[D+1])
SUBW  $DD      Word subtraction with zero page (vAC-=[D]+256*[D+1])
ADDI  $DD      Add small positive constant (vAC+=D)
SUBI  $DD      Subtract small positive constant (vAC-=D)
LSLW  -        Shift left ('ADDW vAC' will not work!) (vAC<<=1)
INC   $DD      Increment zero page byte ([D]++)
ANDI  $DD      Logical-AND with small constant (vAC&=D)
ANDW  $DD      Word logical-AND with zero page (vAC&=[D]+256*[D+1])
ORI   $DD      Logical-OR with small constant (vAC|=D)
ORW   $DD      Word logical-OR with zero page (vAC|=[D]+256*[D+1])
XORI  $DD      Logical-XOR with small constant (vAC^=D)
XORW  $DD      Word logical-XOR with zero page (vAC^=[D]+256*[D+1])
PEEK  -        Read byte from memory (vAC=[vAC])
DEEK  -        Read word from memory (vAC=[vAC]+256*[vAC+1])
POKE  $DD      Write byte in memory ([[D+1],[D]]=vAC&255)
DOKE  $DD      Write word in memory ([[D+1],[D]],[[D+1],[D]+1]=vAC&255,vAC>>8)
LUP   $DD      ROM lookup, needs trampoline in target page (vAC=ROM[D,vAC])
BRA   $DD      Branch unconditionally (vPC=(vPC&0xff00)+D)
BCC   $CC $DD  Test vAC and branch conditionally. CC can be EQ,NE,LT,GT,LE,GE
CALL  $DD      Goto address but remember vPC (vLR,vPC=vPC+2,[D]+256*[D+1]-2)
RET   -        Leaf return (vPC=vLR-2)
PUSH  -        Push vLR on stack ([vSP-2],v[vSP-1],vSP=vLR&255,vLR>>8,vLR-2)
POP   -        Pop address from stack (vLR,vSP=[vSP]+256*[vSP+1],vSP+2)
ALLOC $DD      Create or destroy stack frame (vSP+=D)
SYS   $DD      Native function call using at most 2*T cycles, D=270-max(14,T)
DEF   $DD      Define data or code (vAC,vPC=vPC+2,(vPC&0xff00)+D)
The formulas are pseudo-formal. Take them with a grain of salt.

There's another nice write-up by Frans Faase worth mentioning: Programming the Gigatron


P.S. Maybe it would be nice if SYS can disassemble its operand (negative number of excess "ticks" T) as a number of Gigatron cycles.

Code: Select all

BA FA     SYS  28
Although it's feature creep costing precious RAM footprint, and the cycles are normally not represented in hex either. Ok, bad idea.
Post Reply