Sunday, November 8, 2020

 CARDIAC Simulation using PC/370 - Part 2

CARDIAC Simulation - Part 1 - Introduction to CARDIAC 

CARDIAC Simulation - Part 2 - Primary Logic/Architecture

CARDIAC Simulation - Part 3 - Memory Design / Management

CARDIAC Simulation - Part 4 - CARDIAC Instruction Set Processing 

Welcome back to the 2nd part of my CARDIAC Simulation project (See Part 1 for an Overview). In short CARDIAC represents a mini-CPU with it's own Assembly Language Instruction Set, corresponding Machine Code & active logic flow. It can perform basic functions such as reading input, adding/subtracting, branching & more. My daughter's college computer class used this to demonstrate CPU functionality. It looked pretty cool. I told her I was going to create my own version of the simulator - just for fun of course.

Once again I'm compelled to add a small disclaimer. This exercise was purely for enjoyment within a very limited time frame. It is not an Assembler "purity" test where everyone's individual concept of "purity" should be adhered to. It is strictly a PC/370 version using DOS Interrupts that emulate 370 SVC Calls. There's a multitude of ways & methods to do this... I chose this way. It's slick, elegant, very solid & developed very rapidly.

Time to Design & Build the CARDIAC Simulator

Above: Constructing the CARDIAC Simulator. Spoiler Alert - It works perfectly!

Since the program is mimicking a mini-CPU I decided to call the program TDCPU.ALC - short & sweet.

Designing the Screen Layout - 24x80

My first step was sketching out a screen design suitable for PC/370. It needs to fit nicely within the 24x80 text screen limitation while being aesthetically pleasing with a reasonable resemblance to the online GUI version of the simulator. Unlike GUI development I have to maintain every aspect of the display including calculating cell position to drop data & code into.

  |....5...10...15...20...25...30...35...40...45...50...55...60...65...70...75...80|
==|================================================================================|
01|xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx|
02|x                                                                              x|
03|x  CARDIAC CPU SIMULATION          <F1>=STEP      <F4>=RESET      <ESC>=EXIT   x|
04|x                                                                              x|
05|x      00     10     20     30     40     50     60     70     80     90       x|
06|x      ====   ====   ====   ====   ====   ====   ====   ====   ====   ====     x|
07|x    0:____ 0:____ 0:____ 0:____ 0:____ 0:____ 0:____ 0:____ 0:____ 0:____     x|
08|x    1:____ 1:____ 1:____ 1:____ 1:____ 1:____ 1:____ 1:____ 1:____ 1:____     x|
09|x    2:____ 2:____ 2:____ 2:____ 2:____ 2:____ 2:____ 2:____ 2:____ 2:____     x|
00|x    3:____ 3:____ 3:____ 3:____ 3:____ 3:____ 3:____ 3:____ 3:____ 3:____     x|
11|x    4:____ 4:____ 4:____ 4:____ 4:____ 4:____ 4:____ 4:____ 4:____ 4:____     x|
12|x    5:____ 5:____ 5:____ 5:____ 5:____ 5:____ 5:____ 5:____ 5:____ 5:____     x|
13|x    6:____ 6:____ 6:____ 6:____ 6:____ 6:____ 6:____ 6:____ 6:____ 6:____     x|
14|x    7:____ 7:____ 7:____ 7:____ 7:____ 7:____ 7:____ 7:____ 7:____ 7:____     x|
15|x    8:____ 8:____ 8:____ 8:____ 8:____ 8:____ 8:____ 8:____ 8:____ 8:____     x|
16|x    9:____ 9:____ 9:____ 9:____ 9:____ 9:____ 9:____ 9:____ 9:____ 9:____     x|
17|x                                                                              x|
18|x           PC: ___  ACC: ____  IR: ___  OPCODE: ____  OPERAND: ___            x|
19|x                                                                              x|
20|x  READER:  xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,***    x|
21|x                                                                              x|
22|x  OUTPUT:  xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx   x|
23|x                                                                              x|
24|xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx|

I was happy with the screen design... just enough room to maneuver without looking too crammed.

Input File - CODE & DATA DECK - TDCPU.TXT

The online CARDIAC simulator requires the user to type in the 3 digit code/values on the web page. Each time you return to the page it must be refreshed - that's a lot of tedious redundant typing. I decided to create an input file containing the full source & object code as well as the data values to be used. This way multiple CARDIAC programs can be maintained & tested.

****:PC OOO LLLLLLLL MNE   OOOOOOOO       XXXXXXXXXXXXXXXXXXXXXXXXXXXX
CODE:00 001          DATA  001            ;Initialize Cell 00
CODE:04 000 ctr      DATA  000            ;Initialize Counter
CODE:05 000 sum      DATA  000            ;Initialize Sum
CODE:06 001 one      DATA  001            ;Set Static Variable 1
CODE:07 000 num      DATA  000            ;Initialize Input Number
*
CODE:10 007 loop     INP   num            ;Read/Store Input Value
CODE:11 107          CLA   num            ;Load Accumulator with Value
CODE:12 315          TAC   print          ;Exit Loop when Negative
CODE:13 861          JMP   xproc          ;Perform xproc Subroutine
CODE:14 810          JMP   loop           ;Loop for next Input Value
CODE:15 504 print    OUT   ctr            ;Display Record Count
CODE:16 505          OUT   sum            ;Display Sum Total
CODE:17 900          HRS   00             ;Halt/Reset Program (DONE)
*
CODE:60 000 xsave    DATA  000            ;Accumulator Save Area
CODE:61 660 xproc    STO   xsave          ;Store Accumulator Value
CODE:62 199          CLA   ret99          ;Retrieve Return Address
CODE:63 671          STO   xexit          ;Push Return to Exit
CODE:64 105          CLA   sum            ;Load Accumulator with Sum
CODE:65 207          ADD   num            ;Add Input Value
CODE:66 605          STO   sum            ;Store Accumulator to Sum
CODE:67 104          CLA   ctr            ;Load Accumulator with Count
CODE:68 206          ADD   one            ;Add 1 to Accumulator
CODE:69 604          STO   ctr            ;Store Accumulator to Ctr
CODE:70 160          CLA   xsave          ;Restore Accumulator Value
CODE:71 800 xexit    JMP   00             ;Return to Main Process
*
CODE:99 800 ret99    DATA  800            ;Return Address Area (JMP)
*
****:+NN
DECK:001
DECK:002
DECK:004
DECK:008
DECK:-01

Mainline Processing Logic

The first step of the TDCPU program is to read the input data file (TDCPU.TXT) containing the source/object code and any input data values (if necessary). The Code & data is then stored in the tables CTAB & DTAB. These tables are used to initially populate the Memory Cells and when the <F4> RESET function is pressed. The Main Loop writes the current Memory State to the Screen Variables which are then displayed. The <F1> STEP key will then step through the code associated with the Program Counter - with each opcode branching to the appropriate function. Once the Halt/Reset instruction is executed the <F1> STEP key is inactivated - only <ESC> EXIT & <F4> RESET are permitted. <F4> will reset the program counter, re-initialize memory & re-activate the <F1> STEP key.

***********************************************************************
*        MAINLINE PROCEDURE                                           *
***********************************************************************
         PRINT NOGEN
         SVC   @TRACE                        ISSUE SUPERVISOR CALL
         DC    CL4'IOF '                     KEYBOARD INTERRUPT OFF
*
         XFILO STDWKO                        OPEN OUTPUT FILE
*
         BAL   6,DATA                        LOAD CODE/DECK DATA
RESET    EQU   *
         BAL   6,INIT                        INITIALIZE MEMORY
LOOP     EQU   *
         BAL   6,MEMSCR                      WRITE MEMORY TO SCREEN
         BAL   6,SCREEN                      BUILD SCREEN
*
         CLI   KEY,@K#ESC                    KEY = ESCAPE ???
         BE    LOOPX                         YES - EXIT PLEASE
         CLI   KEY,@K#F4                     KEY = <F4> ???
         BE    RESET                         YES - RESET CARDIAC
*
         CP    XPC,=P'0'                     HALT EXECUTED?
         BE    LOOP                          YES - ONLY RESET/EXIT
*
         CLI   KEY,@K#F1                     KEY = <F1> ???
         BNE   LOOP                          NO  - DISPLAY SCREEN
*
         LA    7,MEMTAB                      LOAD MEMORY ADDRESS
         ZAP   DUBB,XPC                      MOVE PROGRAM COUNTER
         CVB   3,DUBB                        CONVERT TO BINARY
         MH    3,=H'8'                       MULTIPLY BY LENGTH
         AR    7,3                           ADJUST MEMORY PTR
*
         MVC   XIR,0(7)                      SET INSTRUCT REGISTER
         LA    8,OPTAB                       LOAD OPERATION TABLE
IRLOOP   EQU   *
         CLI   0(8),X'FF'                    END OF TABLE???
         BE    LOOP                          YES - INVALID OPCODE
         CLC   0(1,8),XIR                    OPCODE MATCH???
         BE    IRFOUND                       YES - EXIT OPCODE LOOP
         LA    8,8(,8)                       BUMP OPCODE POINTER
         B     IRLOOP                        TEST NEXT OPCODE
IRFOUND  EQU   *
         MVC   XMNE,1(8)                     MOVE INSTRUCTION MNEMONIC
         ZAP   ZPC,XPC                       SAVE PRIOR INSTRUCTION
         AP    XPC,=P'1'                     BUMP PROGRAM COUNTER
         UNPK  XPCU,XPC                      UNPACK PROGRAM COUNTER
         OI    XPCU+2,X'F0'                  TURN ON ZONE BITS
         L     5,4(8)                        LOAD INSTRUCTION ADDRESS
         BALR  6,5                           PERFORM INSTRUCTION
         B     LOOP                          DISPLAY SCREEN AGAIN
LOOPX    EQU   *
         B     RETURN                        EXIT PROGRAM PLEASE
***********************************************************************
 

Build Screen Routine

I developed a generic Screen Display routine that utilizes a WTO Supervisor call that is mapped to Windows PC-Based DOS Interrupts. The table SCTAB contains all the variables that displayed on the page. My algorithm & supporting custom copybooks allow very quick development - even in complex scenarios. The <F1>, <F4> &  <ESC> keys break out of the routine and returns to the main loop.

***********************************************************************
*        BUILD SCREEN                                                 *
***********************************************************************
         DC    F'0'                          RETURN ADDRESS SAVE AREA
SCREEN   EQU   *
         ST    6,*-4                         SAVE RETURN ADDRESS
*
         MVI   VBITS,@BKWT                   SET BG(BLACK)/FG(WHITE)
         BAL   6,VRESET                      CHANGE SCREEN ATTRIBUTES
*
*        DISPLAY SINGLE BOX
*
         MVC   VBX,VBOX2                     LOAD BOX FRAME
         MVC   VBXRC,BXTAB                   LOAD BOX COORDINATES
         BAL   6,VBOX                        DISPLAY BOX FRAME
*
*        DISPLAY SCREEN TEXT
*
         LA    5,SCTAB                       LOAD TABLE ADDRESS
SC1LP    EQU   *
         CLI   0(5),X'FF'                    END OF TABLE ???
         BE    SC1LPX                        YES - EXIT LOOP PLEASE
*
         MVC   VXYS,0(5)                     MOVE CURSOR POSITION
         BAL   6,VXYSET                      SET CURSOR POSITION
         L     2,4(5)                        LOAD MESSAGE ADDRESS
         SVC   @WTO                          ISSUE SUPERVISOR CALL
*
         LA    5,8(,5)                       BUMP TABLE POINTER
         B     SC1LP                         TEST NEXT TABLE ENTRY
SC1LPX   EQU   *
*
*        ACCEPT KEYSTROKE
*
         BAL   6,KBGET                       READ KEYBOARD INPUT
         MVC   KEY,KBCHR                     STORE KEYSTROKE
*
         CLI   KEY,@K#ESC                    KEY = ESCAPE ???
         BE    SC2LPX                        YES - EXIT ROUTINE
         CLI   KEY,@K#F1                     KEY = F1 ???
         BE    SC2LPX                        YES - EXIT ROUTINE
         CLI   KEY,@K#F4                     KEY = F4 ???
         BE    SC2LPX                        YES - EXIT ROUTINE
*
         B     SC1LPX                        BACK TO KEYBOARD
SC2LPX   EQU   *
         MVI   VBITS,@BKWT                   SET BG(BLACK)/FG(WHITE)
         BAL   6,VRESET                      CHANGE SCREEN ATTRIBUTES
SCREENX  EQU   *
         L     6,SCREEN-4                    RESTORE LINK REGISTER
         BR    6                             BRANCH ON LINK REGISTER
***********************************************************************
 

Screen Definition

Below are the primary definitions for the SCREEN Build Routine. Screen variable addresses & their X-Y coordinates are listed in SCTAB. The SCRMEM0 thru SCRMEM9 lines will contain the 100 CARDIAC Memory Cell values. Other display fields include CARDIAC internal registers, instructions, deck reader queue & print output.

***********************************************************************
*        BOX COMPONENTS (COORDINATES/FRAME)                           *
***********************************************************************
BXTAB    DS    0F
         DC    AL1(0,0,23,79)                BOX COORDINATES/FRAME
***********************************************************************
*        SCREEN DISPLAY COMPONENTS                                    *
***********************************************************************
SCTAB    DS    0F
         DC    AL1(0,0,2,3),A(SCRHDR)        SCREEN COORDINATES/MSG
         DC    AL1(0,0,4,7),A(SCRTTL)        SCREEN COORDINATES/MSG
         DC    AL1(0,0,5,7),A(SCRDASH)       SCREEN COORDINATES/MSG
         DC    AL1(0,0,6,5),A(SCRMEM0)       SCREEN COORDINATES/MSG
         DC    AL1(0,0,7,5),A(SCRMEM1)       SCREEN COORDINATES/MSG
         DC    AL1(0,0,8,5),A(SCRMEM2)       SCREEN COORDINATES/MSG
         DC    AL1(0,0,9,5),A(SCRMEM3)       SCREEN COORDINATES/MSG
         DC    AL1(0,0,10,5),A(SCRMEM4)      SCREEN COORDINATES/MSG
         DC    AL1(0,0,11,5),A(SCRMEM5)      SCREEN COORDINATES/MSG
         DC    AL1(0,0,12,5),A(SCRMEM6)      SCREEN COORDINATES/MSG
         DC    AL1(0,0,13,5),A(SCRMEM7)      SCREEN COORDINATES/MSG
         DC    AL1(0,0,14,5),A(SCRMEM8)      SCREEN COORDINATES/MSG
         DC    AL1(0,0,15,5),A(SCRMEM9)      SCREEN COORDINATES/MSG
         DC    AL1(0,0,17,12),A(SCRVAR)      SCREEN COORDINATES/MSG
         DC    AL1(0,0,19,3),A(SCRRDRT)      SCREEN COORDINATES/MSG
         DC    AL1(0,0,19,11),A(SCRRDR)      SCREEN COORDINATES/MSG
         DC    AL1(0,0,21,3),A(SCROUTT)      SCREEN COORDINATES/MSG
         DC    AL1(0,0,21,11),A(SCROUT)      SCREEN COORDINATES/MSG
         DC    XL1'FF'                       END OF TABLE
***********************************************************************
SCRHDR   DC    C'CARDIAC CPU SIMULATION          <F1>=STEP'
         DC    C'      <F4>=RESET      <ESC>=EXIT',C'$'
SCRTTL   DC    C'00     10     20     30     40     '
         DC    C'50     60     70     80     90',C'$'
SCRDASH  DC    C'====   ====   ====   ====   ====   '
         DC    C'====   ====   ====   ====   ====',C'$'
SCRMEM0  DC    C'0:____ 0:____ 0:____ 0:____ 0:____ '
         DC    C'0:____ 0:____ 0:____ 0:____ 0:____',C'$'
SCRMEM1  DC    C'1:____ 1:____ 1:____ 1:____ 1:____ '
         DC    C'1:____ 1:____ 1:____ 1:____ 1:____',C'$'
SCRMEM2  DC    C'2:____ 2:____ 2:____ 2:____ 2:____ '
         DC    C'2:____ 2:____ 2:____ 2:____ 2:____',C'$'
SCRMEM3  DC    C'3:____ 3:____ 3:____ 3:____ 3:____ '
         DC    C'3:____ 3:____ 3:____ 3:____ 3:____',C'$'
SCRMEM4  DC    C'4:____ 4:____ 4:____ 4:____ 4:____ '
         DC    C'4:____ 4:____ 4:____ 4:____ 4:____',C'$'
SCRMEM5  DC    C'5:____ 5:____ 5:____ 5:____ 5:____ '
         DC    C'5:____ 5:____ 5:____ 5:____ 5:____',C'$'
SCRMEM6  DC    C'6:____ 6:____ 6:____ 6:____ 6:____ '
         DC    C'6:____ 6:____ 6:____ 6:____ 6:____',C'$'
SCRMEM7  DC    C'7:____ 7:____ 7:____ 7:____ 7:____ '
         DC    C'7:____ 7:____ 7:____ 7:____ 7:____',C'$'
SCRMEM8  DC    C'8:____ 8:____ 8:____ 8:____ 8:____ '
         DC    C'8:____ 8:____ 8:____ 8:____ 8:____',C'$'
SCRMEM9  DC    C'9:____ 9:____ 9:____ 9:____ 9:____ '
         DC    C'9:____ 9:____ 9:____ 9:____ 9:____',C'$'
SCRVAR   DC    C'PC: __   ACC: ____  IR: ___  '
         DC    C'OPCODE: ___   OPERAND: __ ',C'$'
SCRRDRT  DC    CL7'READER:',C'$'
SCRRDR   DC    CL66' ',C'$'
SCROUTT  DC    CL7'OUTPUT:',C'$'
SCROUT   DC    CL66' ',C'$'
***********************************************************************

This is primarily supporting architecture for the PC/370 CARDIAC Simulator. The trickiest part of the entire process was aligning the cell values with the proper position on the screen. Using the variables SCRMEM0 thru SCRMEM9 as a single table each ten's position has a horizontal offset multiplier of 7 while the one's position has a vertical offset of 70. For example, cell 73 would be in position 7*7 + 3*70 = 259. That would be 8th column (heading=70) residing on the 4th line (SCRMEM3). 

More to come... much more...


Saturday, November 7, 2020

CARDIAC Simulation using PC/370 - Part 1

CARDIAC Simulation - Part 1 - Introduction to CARDIAC 

CARDIAC Simulation - Part 2 - Primary Logic/Architecture

CARDIAC Simulation - Part 3 - Memory Design / Management

CARDIAC Simulation - Part 4 - CARDIAC Instruction Set Processing

CARDIAC stands for "CARDboard Illustrative Aid to Computation" - a learning aid to illustrate how computers function. Created in the 1960's by David Hagelbarger at Bell Labs. My daughter's computer class at Drexel focused on this recently to demonstrate simple concepts such as machine code, assembling source to object, etc. It's based on a memory architecture of 100 cells (0 thru 99) & some internal registers (a program counter & a single accumulator area). There are 10 operation codes (0 thru 9) that control the behavior & flow of the program. Cell values are generally 3 digits & represent either a value or machine code (or both). Primitive but very interesting! 

More information on CARDIAC - Click Here 

At first it appears very abstract, especially when looking at object code through the simulator. When my daughter asked for some guidance I browsed the material & created some code on scrap paper. Then I told her "I'm going to create my own simulator"! 


Above: My CARDIAC PC/370 Simulator after reading all input values. Perfect!

Over Halloween weekend I was able to design, develop & successfully test my PC/370 CARDIAC Simulator. Every move matched the online simulator from my daughter's class. With the exception of some necessary GUI design differences all cells & logic flow was adhered to in sync with each other. The asterisk (*) marks the current location of the Program Counter.

 

Above: The online simulator used in my daughter's class.

The CARDIAC Instruction set. A 2 digit operand is specified after each 1 digit operation code to form the full instruction. The operands generally represent a cell address with the exception being SFT.

Opcode  Mnemonic  Operation
======  ========  ===================================================
0       INP       Read a card into memory
1       CLA       Clear accumulator and add from memory (load)
2       ADD       Add from memory to accumulator
3       TAC       Test accumulator and jump if negative
4       SFT       Shift accumulator
5       OUT       Write memory location to output card
6       STO       Store accumulator to memory
7       SUB       Subtract memory from accumulator
8       JMP       Jump and save PC
9       HRS       Halt and reset
======  ========  ===================================================

CARDIAC Source Assembly Code

The CARDIAC Simulator is based on the 3-digit object code (and values) that are placed in the memory locations 00 thru 99. Once the source assembly code is written it is meticulously translated into the object code format. This is done by hand but it wouldn't be too difficult to create a source code assembler. Maybe my next fun task...

Below is a simple program I wrote that is used in the simulator examples. The source assembly section is on the right with labels, mnemonics, operands & comments. The left side has the resulting cell location & object code contents.

CELL   OBJECT   SOURCE ASSEMBLY CODE
==== | ====== | ============================================================
00   | 001    |          DATA  001            ;Initialize Cell 00
04   | 000    | ctr      DATA  000            ;Initialize Counter
05   | 000    | sum      DATA  000            ;Initialize Sum
06   | 001    | one      DATA  001            ;Set Static Variable 1
07   | 000    | num      DATA  000            ;Initialize Input Number

10   | 007    | loop     INP   num            ;Read/Store Input Value
11   | 107    |          CLA   num            ;Load Accumulator with Value
12   | 315    |          TAC   print          ;Exit Loop when Negative
13   | 861    |          JMP   xproc          ;Perform xproc Subroutine
14   | 810    |          JMP   loop           ;Loop for next Input Value
15   | 504    | print    OUT   ctr            ;Display Record Count
16   | 505    |          OUT   sum            ;Display Sum Total
17   | 900    |          HRS   00             ;Halt/Reset Program (DONE)

60   | 000    | xsave    DATA  000            ;Accumulator Save Area
61   | 660    | xproc    STO   xsave          ;Store Accumulator Value
62   | 199    |          CLA   ret99          ;Retrieve Return Address
63   | 671    |          STO   xexit          ;Push Return to Exit
64   | 105    |          CLA   sum            ;Load Accumulator with Sum
65   | 207    |          ADD   num            ;Add Input Value
66   | 605    |          STO   sum            ;Store Accumulator to Sum
67   | 104    |          CLA   ctr            ;Load Accumulator with Count
68   | 206    |          ADD   one            ;Add 1 to Accumulator
69   | 604    |          STO   ctr            ;Store Accumulator to Ctr
70   | 160    |          CLA   xsave          ;Restore Accumulator Value
71   | 800    | xexit    JMP   00             ;Return to Main Process

99   | 800    | ret99    DATA  800            ;Return Address Area (JPM)
==== | ====== | ============================================================ 
 

The source code label represents the cell location of the instruction or data value. In this example the DATA directives define initial values in cells 04 thru 07 (00 is a special holder) while the actual program code begins in cell 10 (this is a highly recommended standard). The first instruction is INP which reads from the input queue & places the value in the cell with label num (which is 07). The full opcode is 007 (0 for INP & 07 for cell 07). 

The online CARDIAC simulator requires the user to type values into the Deck then click Load to populate the READER queue used by the INP instruction. All code must be typed into the cells by the user as well. In my PC/370 version I store the Code & Deck values in a file that is read & utilized without having to retype the code/data.

CARDIAC PC/370 Simulator in Action:

 Above: My CARDIAC PC/370 Simulator in Action starting from Program Counter = 10.

The simulator begins in program counter 10 & executes each op code one by one - branching to other sections of the program via the JMP (jump) or TAC (Test Accumulator). The line to execute is tracked by the internal variable Program Counter (PC). This particular example loops through the input deck & calculates the count & sum of all records - then displays them via the OUT operation. Watch the asterisk (*) & the program counter (PC) track the current execution line.

This PC/370 CARDIAC Simulator Application was a simple little challenge... but fun.

That's a lot to absorb in a brief post. More to come on the PC/370 simulator version for CARDIAC. Stay tuned...


Wednesday, November 4, 2020

The Farmer, Goat, Wolf & Cabbage Logic Riddle

 My youngest daughter is a freshman in college. She showed me a logic problem in her computer class. She had to design a circuit to solve the riddle (or indicate an error state). The circuit consists of a power source, toggle switches, boolean operators & led displays - each of the pieces connects to one another. I vaguely remember this riddle from long ago. I thought it would be fun to create a simple PC/370 application to track & evaluate the movements:

General Instructions:


A farmer must carry a goat, a wolf and a head of cabbage across the river (on the right). He can only carry one item at a time. The farmer must be on the same side as the item he will carry. <F1> moves the farmer only while <F2> thru <F4> moves the farmer and the object. The goat cannot be left alone with the cabbage or the wolf. If so, the goat or cabbage will be eaten.

Not too complicated. The key sequence to solve the puzzle correctly is:

               <F2> <F1> <F3> <F2> <F4> <F1> <F2>

Above: Screen animation of puzzle completion.


 

Above: Error Message if farmer leaves goat alone with the wolf - *** WOLF EATS THE GOAT ***.

Each press of a key toggles the object(s) to the left & right. Then the state is evaluated with an error message produced (or winner message).

Above: All items are safely across the river. ***WINNER***!

There are three key elements of code. First is the main loop that detects function key input. The only keys active are <F1> thru <F4> to move the characters/items, <F10> to reset the game from scratch & the <ESC> key to Exit. The second element is the TOGGLE routine that moves the farmer alone or with an item from LEFT to RIGHT or vice versa. The farmer is the central character since he's doing all the work. The third element is the VALIDATE routine that tests if the farmer is with the goat - and if not, is the goat alone with the wolf or the cabbage? If so, that's an error...

LOOP     EQU   *
         BAL   6,VALIDATE                    VALIDATE STATE
         BAL   6,SCREEN                      BUILD SCREEN
*
         CLI   KEY,@K#ESC                    KEY = ESCAPE ???
         BE    LOOPX                         YES - EXIT PLEASE
*
         CLI   KEY,@K#F1                     KEY = F1 ???
         BE    LOOPF1                        YES - PROCESS KEY
         CLI   KEY,@K#F2                     KEY = F2 ???
         BE    LOOPF2                        YES - PROCESS KEY
         CLI   KEY,@K#F3                     KEY = F3 ???
         BE    LOOPF3                        YES - PROCESS KEY
         CLI   KEY,@K#F4                     KEY = F4 ???
         BE    LOOPF4                        YES - PROCESS KEY
*
         CLI   KEY,@K#F10                    KEY = F10 ???
         BNE   LOOP                          NO  - LOOP AGAIN
LOOPF10  EQU   *
         MVC   XF(4),=CL4'LLLL'              ALL BACK TO THE LEFT
         MVC   SCRFL,=CL7'FARMER'            INIT LEFT  FARMER
         MVC   SCRFR,=CL7' '                 INIT RIGHT FARMER
         MVC   SCRGL,=CL7'GOAT'              INIT LEFT  GOAT
         MVC   SCRGR,=CL7' '                 INIT RIGHT GOAT
         MVC   SCRWL,=CL7'WOLF'              INIT LEFT  WOLF
         MVC   SCRWR,=CL7' '                 INIT RIGHT WOLF
         MVC   SCRCL,=CL7'CABBAGE'           INIT LEFT  CABBAGE
         MVC   SCRCR,=CL7' '                 INIT RIGHT CABBAGE
         MVI   SCRMSG,C' '                   MOVE BLANK TO MSG
         MVC   SCRMSG+1(L'SCRMSG-1),SCRMSG   PROPAGATE THROUGHOUT
         B     LOOP                          DISPLAY SCREEN AGAIN
LOOPF1   EQU   *
         LA    4,XF                          SET STATE  ADDRESS
         LA    5,SCRFL                       SET SCREEN ADDRESS
         BAL   6,TOGGLE                      TOGGLE POSITIONS
         B     LOOP                          DISPLAY SCREEN AGAIN
LOOPF2   EQU   *
         LA    4,XG                          SET STATE  ADDRESS
         LA    5,SCRGL                       SET SCREEN ADDRESS
         BAL   6,TOGGLE                      TOGGLE POSITIONS
         B     LOOP                          DISPLAY SCREEN AGAIN
LOOPF3   EQU   *
         LA    4,XW                          SET STATE  ADDRESS
         LA    5,SCRWL                       SET SCREEN ADDRESS
         BAL   6,TOGGLE                      TOGGLE POSITIONS
         B     LOOP                          DISPLAY SCREEN AGAIN
LOOPF4   EQU   *
         LA    4,XC                          SET STATE  ADDRESS
         LA    5,SCRCL                       SET SCREEN ADDRESS
         BAL   6,TOGGLE                      TOGGLE POSITIONS
         B     LOOP                          DISPLAY SCREEN AGAIN
LOOPX    EQU   *
 

The TOGGLE routine flips the orientation of the farmer/item & moves it to the new destination. Exclusive OR (XOC) is used to isolate & swap the bits - producing the "toggle" effect.

***********************************************************************
*        TOGGLE POSITIONS                                             *
***********************************************************************
         DC    F'0'                          RETURN ADDRESS SAVE AREA
TOGGLE   EQU   *
         ST    6,*-4                         SAVE RETURN ADDRESS
*
         CLC   XF,0(4)                       FARMER STATE EQUAL?
         BNE   LOOP                          NO  - IGNORE KEY
*
         CLI   XF,C'L'                       CURRENT STATE LEFT?
         BE    *+12                          YES - SET TO RIGHT
         MVI   XF,C'L'                       NO  - SET TO LEFT
         B     *+8                           CONTINUE PLEASE
         MVI   XF,C'R'                       SET STATE = RIGHT
*
         XC    SCRFL,SCRFR                   ISOLATE UNIQUE BITS
         XC    SCRFR,SCRFL                   REPLACE RIGHT SIDE
         XC    SCRFL,SCRFR                   REPLACE LEFT  SIDE
*
         CLI   KEY,@K#F1                     KEY = F1 ???
         BE    TOGGLEX                       YES - EXIT ROUTINE
*
         MVC   0(1,4),XF                     SYNCHRONIZE STATE
         XC    0(7,5),8(5)                   ISOLATE UNIQUE BITS
         XC    8(7,5),0(5)                   REPLACE RIGHT SIDE
         XC    0(7,5),8(5)                   REPLACE LEFT  SIDE
TOGGLEX  EQU   *
         L     6,TOGGLE-4                    RESTORE LINK REGISTER
         BR    6                             BRANCH ON LINK REGISTER
***********************************************************************
         EJECT
 

Not much else to say about that... except to add some PC/370 source code.

TDFGWC.ALC - Full Source Code:

As usual, this is the full source code minus the Copybooks for Screen, Video & Key handling. Also, some commonly used variables & copybooks may appear although they aren't utilized - this makes cloning for other exercises quicker.

         TITLE 'TDFGWC   - PC/370 4.2 // DELIA'
***********************************************************************
*                                                                     *
*        MODULE:  TDFGWC.                                             *
*        AUTHOR:  TONY DELIA.                                         *
*          DATE:  10/22/2020.                                         *
*          DESC:  PC/370 FARMER GAME.                                 *
*          NOTE:  PC/370 RELEASE 4.2                                  *
*                                                                     *
***********************************************************************
         EJECT
***********************************************************************
*        T  D  F  G  W  C           P  R  O  G  R  A  M               *
***********************************************************************
TDFGWC   START 0                             START PROGRAM
         STM   14,12,12(13)                  SAVE REGISTERS
         LR    12,15                         LOAD PROGRAM ENTRY POINT
         USING TDFGWC+0*4096,12              BASE REGISTER 1
         L     11,BASE2                      LOAD BASE REGISTER 2
         USING TDFGWC+1*4096,11              TELL ASSEMBLER ABOUT BASE2
         L     10,BASE3                      LOAD BASE REGISTER 3
         USING TDFGWC+2*4096,10              TELL ASSEMBLER ABOUT BASE3
         ST    13,SAVE+4                     SAVE EXTERNAL SAVE ADDRESS
         LR    14,13                         XFER ADDRESS TO TEMP R14
         LA    13,SAVE                       LOAD INTERNAL SAVE ADDRESS
         ST    13,8(14)                      SAVE IN EXTERNAL SAVE AREA
         B     GO                            BRANCH TO PROCESSING RTN
***********************************************************************
RETURN   EQU   *                             TIME TO RETURN
         L     13,SAVE+4                     RESTORE REGISTER 13
         LM    14,12,12(13)                  RESTORE REMAINING REGS
         SR    15,15                         CLEAR RETURN CODE
         BR    14                            BRANCH TO CALLING PROGRAM
***********************************************************************
SAVE     DC    18F'0'                        S A V E   A R E A
***********************************************************************
BASE2    DC    A(TDFGWC+1*4096)              BASE2 DISPLACEMENT
BASE3    DC    A(TDFGWC+2*4096)              BASE3 DISPLACEMENT
***********************************************************************
GO       EQU   *                             BEGIN PROCESSING ...
***********************************************************************
         EJECT
***********************************************************************
*        MAINLINE PROCEDURE                                           *
***********************************************************************
         PRINT NOGEN
         SVC   @TRACE                        ISSUE SUPERVISOR CALL
         DC    CL4'IOF '                     KEYBOARD INTERRUPT OFF
*
LOOP     EQU   *
         BAL   6,VALIDATE                    VALIDATE STATE
         BAL   6,SCREEN                      BUILD SCREEN
*
         CLI   KEY,@K#ESC                    KEY = ESCAPE ???
         BE    LOOPX                         YES - EXIT PLEASE
*
         CLI   KEY,@K#F1                     KEY = F1 ???
         BE    LOOPF1                        YES - PROCESS KEY
         CLI   KEY,@K#F2                     KEY = F2 ???
         BE    LOOPF2                        YES - PROCESS KEY
         CLI   KEY,@K#F3                     KEY = F3 ???
         BE    LOOPF3                        YES - PROCESS KEY
         CLI   KEY,@K#F4                     KEY = F4 ???
         BE    LOOPF4                        YES - PROCESS KEY
*
         CLI   KEY,@K#F10                    KEY = F10 ???
         BNE   LOOP                          NO  - LOOP AGAIN
LOOPF10  EQU   *
         MVC   XF(4),=CL4'LLLL'              ALL BACK TO THE LEFT
         MVC   SCRFL,=CL7'FARMER'            INIT LEFT  FARMER
         MVC   SCRFR,=CL7' '                 INIT RIGHT FARMER
         MVC   SCRGL,=CL7'GOAT'              INIT LEFT  GOAT
         MVC   SCRGR,=CL7' '                 INIT RIGHT GOAT
         MVC   SCRWL,=CL7'WOLF'              INIT LEFT  WOLF
         MVC   SCRWR,=CL7' '                 INIT RIGHT WOLF
         MVC   SCRCL,=CL7'CABBAGE'           INIT LEFT  CABBAGE
         MVC   SCRCR,=CL7' '                 INIT RIGHT CABBAGE
         MVI   SCRMSG,C' '                   MOVE BLANK TO MSG
         MVC   SCRMSG+1(L'SCRMSG-1),SCRMSG   PROPAGATE THROUGHOUT
         B     LOOP                          DISPLAY SCREEN AGAIN
LOOPF1   EQU   *
         LA    4,XF                          SET STATE  ADDRESS
         LA    5,SCRFL                       SET SCREEN ADDRESS
         BAL   6,TOGGLE                      TOGGLE POSITIONS
         B     LOOP                          DISPLAY SCREEN AGAIN
LOOPF2   EQU   *
         LA    4,XG                          SET STATE  ADDRESS
         LA    5,SCRGL                       SET SCREEN ADDRESS
         BAL   6,TOGGLE                      TOGGLE POSITIONS
         B     LOOP                          DISPLAY SCREEN AGAIN
LOOPF3   EQU   *
         LA    4,XW                          SET STATE  ADDRESS
         LA    5,SCRWL                       SET SCREEN ADDRESS
         BAL   6,TOGGLE                      TOGGLE POSITIONS
         B     LOOP                          DISPLAY SCREEN AGAIN
LOOPF4   EQU   *
         LA    4,XC                          SET STATE  ADDRESS
         LA    5,SCRCL                       SET SCREEN ADDRESS
         BAL   6,TOGGLE                      TOGGLE POSITIONS
         B     LOOP                          DISPLAY SCREEN AGAIN
LOOPX    EQU   *
         B     RETURN                        EXIT PROGRAM PLEASE
***********************************************************************
         EJECT
***********************************************************************
*        TOGGLE POSITIONS                                             *
***********************************************************************
         DC    F'0'                          RETURN ADDRESS SAVE AREA
TOGGLE   EQU   *
         ST    6,*-4                         SAVE RETURN ADDRESS
*
         CLC   XF,0(4)                       FARMER STATE EQUAL?
         BNE   LOOP                          NO  - IGNORE KEY
*
         CLI   XF,C'L'                       CURRENT STATE LEFT?
         BE    *+12                          YES - SET TO RIGHT
         MVI   XF,C'L'                       NO  - SET TO LEFT
         B     *+8                           CONTINUE PLEASE
         MVI   XF,C'R'                       SET STATE = RIGHT
*
         XC    SCRFL,SCRFR                   ISOLATE UNIQUE BITS
         XC    SCRFR,SCRFL                   REPLACE RIGHT SIDE
         XC    SCRFL,SCRFR                   REPLACE LEFT  SIDE
*
         CLI   KEY,@K#F1                     KEY = F1 ???
         BE    TOGGLEX                       YES - EXIT ROUTINE
*
         MVC   0(1,4),XF                     SYNCHRONIZE STATE
         XC    0(7,5),8(5)                   ISOLATE UNIQUE BITS
         XC    8(7,5),0(5)                   REPLACE RIGHT SIDE
         XC    0(7,5),8(5)                   REPLACE LEFT  SIDE
TOGGLEX  EQU   *
         L     6,TOGGLE-4                    RESTORE LINK REGISTER
         BR    6                             BRANCH ON LINK REGISTER
***********************************************************************
         EJECT
***********************************************************************
*        VALIDATE STATE                                               *
***********************************************************************
         DC    F'0'                          RETURN ADDRESS SAVE AREA
VALIDATE EQU   *
         ST    6,*-4                         SAVE RETURN ADDRESS
*
         MVI   SCRMSG,C' '                   MOVE BLANK TO MSG
         MVC   SCRMSG+1(L'SCRMSG-1),SCRMSG   PROPAGATE THROUGHOUT
*
         CLC   XG,XF                         GOAT WITH FARMER?
         BE    VALIDATZ                      YES - NO DANGER
*
         CLC   XG,XW                         GOAT WITH WOLF???
         BNE   *+14                          NO  - OKAY SO FAR
         MVC   SCRMSG,ERRW                   YES - ERROR MESSAGE
         B     VALIDATX                      EXIT ROUTINE NOW
*
         CLC   XG,XC                         GOAT WITH CABBAGE???
         BNE   VALIDATX                      NO  - EXIT ROUTINE
         MVC   SCRMSG,ERRC                   YES - ERROR MESSAGE
         B     VALIDATX                      EXIT ROUTINE NOW
VALIDATZ EQU   *
         CLC   XF(4),=C'RRRR'                ALL ITEMS ON RIGHT?
         BNE   VALIDATX                      NO  - EXIT ROUTINE
         MVC   SCRMSG,WINMSG                 YES - GAME IS WON!
VALIDATX EQU   *
         L     6,VALIDATE-4                  RESTORE LINK REGISTER
         BR    6                             BRANCH ON LINK REGISTER
***********************************************************************
         EJECT
***********************************************************************
*        BUILD SCREEN                                                 *
***********************************************************************
         DC    F'0'                          RETURN ADDRESS SAVE AREA
SCREEN   EQU   *
         ST    6,*-4                         SAVE RETURN ADDRESS
*
         MVI   VBITS,@BKWT                   SET BG(BLACK)/FG(WHITE)
         BAL   6,VRESET                      CHANGE SCREEN ATTRIBUTES
*
*        DISPLAY SINGLE BOX
*
         MVC   VBX,VBOX2                     LOAD BOX FRAME
         MVC   VBXRC,BXTAB                   LOAD BOX COORDINATES
         BAL   6,VBOX                        DISPLAY BOX FRAME
*
*        DISPLAY SCREEN TEXT
*
         LA    5,SCTAB                       LOAD TABLE ADDRESS
SC1LP    EQU   *
         CLI   0(5),X'FF'                    END OF TABLE ???
         BE    SC1LPX                        YES - EXIT LOOP PLEASE
*
         MVC   VXYS,0(5)                     MOVE CURSOR POSITION
         BAL   6,VXYSET                      SET CURSOR POSITION
         L     2,4(5)                        LOAD MESSAGE ADDRESS
         SVC   @WTO                          ISSUE SUPERVISOR CALL
*
         LA    5,8(,5)                       BUMP TABLE POINTER
         B     SC1LP                         TEST NEXT TABLE ENTRY
SC1LPX   EQU   *
*
*        ACCEPT KEYSTROKE
*
         BAL   6,KBGET                       READ KEYBOARD INPUT
         MVC   KEY,KBCHR                     STORE KEYSTROKE
*
         CLI   KEY,@K#ESC                    KEY = ESCAPE ???
         BE    SC2LPX                        YES - EXIT ROUTINE
         CLI   KEY,@K#F1                     KEY = F1 ???
         BE    SC2LPX                        YES - EXIT ROUTINE
         CLI   KEY,@K#F2                     KEY = F2 ???
         BE    SC2LPX                        YES - EXIT ROUTINE
         CLI   KEY,@K#F3                     KEY = F3 ???
         BE    SC2LPX                        YES - EXIT ROUTINE
         CLI   KEY,@K#F4                     KEY = F4 ???
         BE    SC2LPX                        YES - EXIT ROUTINE
         CLI   KEY,@K#F10                    KEY = F10 ???
         BE    SC2LPX                        YES - EXIT ROUTINE
*
         B     SC1LPX                        BACK TO KEYBOARD
SC2LPX   EQU   *
         MVI   VBITS,@BKWT                   SET BG(BLACK)/FG(WHITE)
         BAL   6,VRESET                      CHANGE SCREEN ATTRIBUTES
SCREENX  EQU   *
         L     6,SCREEN-4                    RESTORE LINK REGISTER
         BR    6                             BRANCH ON LINK REGISTER
***********************************************************************
         EJECT
***********************************************************************
*        WORKING STORAGE                                              *
***********************************************************************
DUBB     DC    D'0'                          DOUBLEWORD
FULL     DC    F'0'                          FULLWORD
HALF     DC    H'0'                          HALFWORD
KEY      DC    CL1' '                        KEY STROKE (@RDKEY)
CHAR     DC    CL1' ',C'$'                   KEY CHARACTER
@YES     EQU   C'Y'                          YES
@NO      EQU   C'N'                          NO
@ESC     EQU   27                            ESCAPE KEY
@CR      EQU   13                            CARRIAGE RETURN
@LF      EQU   10                            LINE FEED
@KEYLO   EQU   32                            ASCII KEY - LO VALUE
@KEYHI   EQU   126                           ASCII KEY - HI VALUE
XF       DC    CL1'L'                        STATE - FARMER
XG       DC    CL1'L'                        STATE - GOAT
XW       DC    CL1'L'                        STATE - WOLF
XC       DC    CL1'L'                        STATE - CABBAGE
ERRW     DC    CL60'ERROR *** WOLF EATS THE GOAT ***'
ERRC     DC    CL60'ERROR *** GOAT EATS THE CABBAGE ***'
WINMSG   DC    CL60'***WINNER*** THE FARMER DID IT! ***'
***********************************************************************
         LTORG                               LITERAL POOL
***********************************************************************
*        COPYBOOKS                                                    *
***********************************************************************
         COPY  CPY/TDBOX.CPY                 COPYBOOK - BOX DISPLAY
         COPY  CPY/TDVID.CPY                 COPYBOOK - VIDEO UTILITY
         COPY  CPY/TDKBD.CPY                 COPYBOOK - KEYBOARD INPUT
         COPY  CPY/TDKEY.CPY                 COPYBOOK - KEYSTROKES
         COPY  CPY/TDCLR.CPY                 COPYBOOK - COLORS
         COPY  CPY/TDSVC.CPY                 COPYBOOK - SUPERVISOR
***********************************************************************
*        BOX COMPONENTS (COORDINATES/FRAME)                           *
***********************************************************************
BXTAB    DS    0F
         DC    AL1(0,0,23,79)                BOX COORDINATES/FRAME
***********************************************************************
*        SCREEN DISPLAY COMPONENTS                                    *
***********************************************************************
SCTAB    DS    0F
         DC    AL1(0,0,2,2),A(SCR01)         SCREEN COORDINATES/MSG
         DC    AL1(0,0,4,13),A(SCR02L)       SCREEN COORDINATES/MSG
         DC    AL1(0,0,4,34),A(SCR02R)       SCREEN COORDINATES/MSG
         DC    AL1(0,0,5,13),A(SCR03L)       SCREEN COORDINATES/MSG
         DC    AL1(0,0,5,34),A(SCR03R)       SCREEN COORDINATES/MSG
         DC    AL1(0,0,6,13),A(SCRFL)        SCREEN COORDINATES/MSG
         DC    AL1(0,0,6,34),A(SCRFR)        SCREEN COORDINATES/MSG
         DC    AL1(0,0,7,13),A(SCRGL)        SCREEN COORDINATES/MSG
         DC    AL1(0,0,7,34),A(SCRGR)        SCREEN COORDINATES/MSG
         DC    AL1(0,0,8,13),A(SCRWL)        SCREEN COORDINATES/MSG
         DC    AL1(0,0,8,34),A(SCRWR)        SCREEN COORDINATES/MSG
         DC    AL1(0,0,9,13),A(SCRCL)        SCREEN COORDINATES/MSG
         DC    AL1(0,0,9,34),A(SCRCR)        SCREEN COORDINATES/MSG
         DC    AL1(0,0,10,13),A(SCR03L)      SCREEN COORDINATES/MSG
         DC    AL1(0,0,10,34),A(SCR03R)      SCREEN COORDINATES/MSG
         DC    AL1(0,0,12,2),A(SCR04A)       SCREEN COORDINATES/MSG
         DC    AL1(0,0,12,13),A(SCRMSG)      SCREEN COORDINATES/MSG
         DC    AL1(0,0,14,2),A(SCR05A)       SCREEN COORDINATES/MSG
         DC    AL1(0,0,14,11),A(SCR05B)      SCREEN COORDINATES/MSG
         DC    AL1(0,0,15,11),A(SCR06A)      SCREEN COORDINATES/MSG
         DC    AL1(0,0,16,11),A(SCR07A)      SCREEN COORDINATES/MSG
         DC    AL1(0,0,17,11),A(SCR08A)      SCREEN COORDINATES/MSG
         DC    AL1(0,0,18,11),A(SCR09A)      SCREEN COORDINATES/MSG
         DC    AL1(0,0,19,11),A(SCR10A)      SCREEN COORDINATES/MSG
         DC    AL1(0,0,21,11),A(SCR11A)      SCREEN COORDINATES/MSG
         DC    XL1'FF'                       END OF TABLE
***********************************************************************
SCR01    DC    C'<F1>=FARMER*  <F2>=GOAT  <F3>=WOLF  <F4>=CABBAGE  '
         DC    C'<F10>=RESET  <ESC>=EXIT',C'$'
SCR02L   DC    C'LEFT',C'$'
SCR02R   DC    C'RIGHT',C'$'
SCR03L   DC    C'==========',C'$'
SCR03R   DC    C'==========',C'$'
SCRFL    DC    CL7'FARMER',C'$'
SCRFR    DC    CL7' ',C'$'
SCRGL    DC    CL7'GOAT',C'$'
SCRGR    DC    CL7' ',C'$'
SCRWL    DC    CL7'WOLF',C'$'
SCRWR    DC    CL7' ',C'$'
SCRCL    DC    CL7'CABBAGE',C'$'
SCRCR    DC    CL7' ',C'$'
SCR04A   DC    C'MESSAGE:',C'$'
SCRMSG   DC    CL60' ',C'$'
SCR05A   DC    C'  RULES:',C'$'
SCR05B   EQU   *
         DC    C'A FARMER MUST CARRY A GOAT, A WOLF AND '
         DC    C'A HEAD OF CABBAGE ACROSS',C'$'
SCR06A   EQU   *
         DC    C'THE RIVER (ON THE RIGHT). HE CAN ONLY '
         DC    C'CARRY ONE THING AT A TIME.',C'$'
SCR07A   EQU   *
         DC    C'THE FARMER MUST BE ON THE SAME SIDE AS '
         DC    C'THE ITEM HE WILL CARRY.',C'$'
SCR08A   EQU   *
         DC    C'<F1> MOVES THE FARMER ONLY WHILE <F2> '
         DC    C'THRU <F4> MOVES THE FARMER',C'$'
SCR09A   EQU   *
         DC    C'AND THE OBJECT. THE GOAT CANNOT BE LEFT '
         DC    C'ALONE WITH THE CABBAGE OR',C'$'
SCR10A   EQU   *
         DC    C'THE WOLF. IF SO, THE GOAT OR CABBAGE '
         DC    C'WILL BE EATEN!',C'$'
SCR11A   EQU   *
         DC    C'THE <F1>-<F4> KEYS TOGGLE THE ITEMS TO '
         DC    C'THE LEFT & RIGHT.',C'$'
***********************************************************************
         END   TDFGWC
 

 That was simple but fun... my next post will be a bit more complex. Another idea from my daughter's class - this time creating a fully functional Cardiac CPU Simulator - complete with it's own assembly instructions & machine code.