Michael Alyn Miller

MFORTH 1.1


Version 1.1.04B1 of MFORTH, my Forth environment for the M100/M102 laptops, has now been released. Binaries can be found on the MFORTH page.

This version adds a couple of important features, namely an integrated 8085 assembler and the completion of the multitasking system. You can now write M100 programs in both ANS Forth as well as 8085 assembler using MFORTH, although for the most part I would recommend that you use the assembler to access parts of the M100 that MFORTH does not yet expose and/or to accelerate performance-critical portions of your software. Forth is plenty fast for almost anything that you would need to do (most of MFORTH is written in Forth, not assembler).

Assembler

Here is an example of how to use the assembler, the following code gives you access to the Main ROM’s “PLOT” routine, which draws a pixel at any location on the screen:

code plot ( x y --)
saveregs
h pop  l e mov
h pop  l d mov
29772 romcall
restoreregs next
end-code

You can then use “PLOT” just like any other MFORTH word:

120 30 plot  120 31 plot  120 32 plot  120 33 plot

Note that the MFORTH assembler is a traditional, postfix assembler, so the arguments are “reversed” from how they might look in something like TASM. That said, the MFORTH assembler also has all of the power of the Forth environment, so you can easily write loops and if statements without having to deal with labels. Here is an example of a word that converts a lower case string to upper case:

hex
code toupper ( c-addr u --)
saveregs
d pop  h pop
begin
    d a mov  e ora  0<>
while
    m a mov  60 cpi  cc
    if  20 sui  a m mov  then
    d dcx  h inx
repeat
restoreregs next
end-code
decimal

Here is how to use the new word:

S" Hello World"  2DUP TOUPPER TYPE

(outputs HELLO WORLD)

Multitasking System

The multitasking system is also a fun new addition and will be featured pretty heavily in some of the additional work that I have planned for MFORTH. In a nutshell, you can create multiple tasks and have them execute alongside each other, even while you are writing more code and interacting with MFORTH. Tasks are very small (256 bytes), so you can fit a lot of them into RAM before you will run into problems. That said, I would be surprised if anyone needed more than a couple of tasks, even for the most complex program. Tasks are created by passing an xt to the TASK word; the task will then run that xt until it returns (which, in most cases, it should never do). Tasks can suspend themselves and give time to the next task by calling PAUSE and should do that fairly often. The primary task (the one that provides the text interpreter) calls PAUSE every time it checks the keyboard queue, for example.

Here is an example of a task that displays a clock in the upper-right corner of the screen. The clock will continue to update, even as you do other things in MFORTH:

: .NN ( u) 0 <# # # #> TYPE ;
: .NNNN ( u) 0 <# # # # # #> TYPE ;
: .-  [CHAR] - EMIT ;
: .DATE ( d m y) .NNNN .- .NN .- .NN ;
: .:  [CHAR] : EMIT ;
: .TIME ( s m h) .NN .: .NN .: .NN ;
: .TIME&DATE  TIME&DATE .DATE SPACE .TIME ;
: SEC ( --u) TIME&DATE 2DROP 2DROP DROP ;
: NEWSEC? ( u1--u2 f) SEC TUCK <> ;
: .CLOCK  GET-XY  21 0 AT-XY  .TIME&DATE  AT-XY ;
: CLOCK  0 BEGIN NEWSEC? IF .CLOCK THEN PAUSE AGAIN ;

You start the clock by typing:

' CLOCK TASK

There is no way to stop the clock display other than to exit MFORTH.

That’s the code exactly as I typed it in to my M102, but I would be happy to go into detail as to what each of the words are doing if people are interested.

Enjoy the new version of MFORTH, and please let me know if you have any questions about how to use the new features (or any of the old features).