Skip to content
LeFauve edited this page Feb 5, 2024 · 16 revisions

Hellorld! on Computer Trainers

This is a page dedicated to seeing "Hellorld!" run on Computer Trainers. This is an interesting classification of computers. On the surface, they seem like microcomputers, but when you look a little closer, there are some notable differences. For here though, we're classifying computer trainers as Single Board Computers (SBCs) with the keyboard and/or display integrated into the board. The keyboard doesn't, and often isn't, haveto be a full sized qwerty keyboard either. Listings are in alphabetical order.

Quick links:

Rockwell AIM-65 Digirule 2U Multitech MPF-1 Multitech MPF-1P (w/ VFD)
PROFI-5/50E Protec PRO-83 RCA VIP NEC TK-80/TK-85

Rockwell AIM-65

The Rockwell AIM-65 was introduced in 1978 as a 6502 trainer. Interestingly, it is quite similar to the KIM-1, only with more features and capability. Unlike most other trainers, it has a Built-in full-sized QWERTY keyboard, a 20 character alphanumeric LED display (16 segments), an integrated 20 character thermal printer, and a 20 mA current-loop serial interface that can be adapted to RS-232. With a 6502, 6522, 4kB of RAM, and five sockets for expanded ROM, it's a quite capable little machine. But can it "Hellorld!"? You betcha!

Code:

==0000
       .OPT LIS, GEN, NOE

; WRITTEN FOR THE AIM-65
; BY JOHN JONES OCTOBER 2023

; ENTRY ADDRS OF USED MONITOR SUBROUTINES
; ---------------------------------------
==0000 CRLF=$E9F0
==0000 OUTALL=$E9BC
==0000 CRCK=$EA24

; MAIN PROGRAM
; ------------
; START ADDRESS
==0000
       *=$0200

==0200
; OUTPUT A CR AND LF TO ACTIVE OUTPUT DEVICE
20F0E9 JSR CRLF

; LOAD #FF INTO X SO IT CAN INC FROM #00
A2FF   LDX #$FF

; START OF LOOP TO LOAD AND OUTPUT MSG1 CHARS
==0205 LOOP1

; INCREMENT X
E8     INX

; LOAD X CHAR OF MSG1 INTO A
BD1702 LDA MSG1,X

; CHECK IF CHAR IS THE TERMINATING CHAR (;)
C93B   CMP #';'

; IF TERMINATING CHAR DETECTED BRANCH TO PRT
F006   BEQ PRT

; OUTPUT CONTENT OF A TO DEFAULT OUTPUT DEVICE AS ASCII
20BCE9 JSR OUTALL

; JUMP BACK TO START OF LOOP
4C0502 JMP LOOP1

==0213 PRT
; OUTPUT PRINT BUFFER
2024EA JSR CRCK
60     RTS

; MESSAGE TO PRINT
; ----------------
==0217 MSG1
2048   .BYT ' HELLORLD!;'
454C
4C4F
524C
44213B

; END DIRECTIVE
; ----------------
       .END

Which gives us a trifecta of output, on the hex displays, the integrated printer and on the terminal!

Digirule 2U

The Digirule 2U was a kickstarter back in 2020. It's an opensource pocket computer using a modern microcontroller to emulate a fantasy 8 bits CPU with a basic front panel interface.

As describbed by its creator "The Digirule 2U is basically an 8-bit programmable computer from the 1970's, built into a 20cm Ruler".

It's very limited, even by the 70's standard (256 bytes of address space, two groups of 8 leds for display and 8 momentary switches for input) but it's very convenient to use on the go (the whole thing fits in a pocket and is powered with a single CR2032) and pretty fun to write for.

You can also connect it to a PC (USB C) or a serial terminal and use a more advanced monitor if you prefer.

Digirule2U

And it can of course "Hellord!" :o)

The 33 bytes program will both flash the ASCII code of each letter on the D0-D7 LEDs and send it to the serial port (if a console is connected).

Source:

; Hellorld!
; Flash the Hellorld! string in the data register leds and send it to serial port
            ORG 0      ; Start of the code
            speed 0x70 ; Slow down the CPU so we can see the leds flashing

            copylr Hellorld,CurrentChar ; Point to the first character of Hellorld string

Loop
            copylr 0,_dr       ; Blank the data register (switch all leds off)
            copyia CurrentChar ; Copy next character in accumulator
            btstsc _z,_sr      ; Test bit Z of status register, and skip 2 bytes if clear
            halt               ; End of program
            nop                ; filler
            copyar _dr         ; copy accumulator in the data register (Leds)
            comout             ; send character to serial port
            incr CurrentChar   ; point to the next char in the string
            jump Loop          ; ...and continue

Hellorld    byte 'H','e','l','l','o','r','l','d','!',0
CurrentChar byte 42 
            END 0

If you want to load it from the serial console, here is a ready to use hexdump:

:1000000002700516200500FF0C202600FC000107E9
:10001000FFC01E20280548656C6C6F726C6421005F
:010020002AB5
:00000001FF

If you prefer to enter the program using the "front panel", here is a list of bytes to be entered starting at address 0x00:

02 70 05 16 20 05 00 FF 0C 20 26 00 FC 00 01 07  |.p.. .... &.....|
FF C0 1E 20 28 05 48 65 6C 6C 6F 72 6C 64 21 00  |... (.Hellorld!.|

And here is a video where you can see the program in action: https://youtu.be/6IpT-52ig0I

Multitech MPF-1 (aka Microprofessor)

The MPF-1 was introduced in 1981 as a training board to teach the fundamentals of Z80 assembly in schools and colleges. Featuring a Z80-A running at 1.7MHz it supports 158 instructions, programmed as hex using a modest keyboard, and a 6 character 7-segment display to show various parameters about the system. It has a ROM monitor program that runs in the background. Admittedly this code does CALL the screen drawing routine, which reads in 6 bytes from an address starting at the location pointed at by register IX, with each byte broken down into binary coded segment positions. It uses a nested loop of XTHL (Stack exchange HL-HL') to slow the output to a readable speed. HELLORLD! does not fit in 6 characters, so the scroll was deemed necessary.

MPF-1 in middle of Hellorld Code

1800	LD IX, &184D	DD 21 4D 18		;Display register text string starts at &184D
1804	LD A, &11	3E 11			;Length of text string
1806	LD &1820, A	32 20 18		;Stick that into scratch memory at &1820

1809	CALL &0624	CD 24 06		;Display what IX points to
180C	CALL &1821	CD 21 18		;CALL the pause loop
180F	LD A, &1820	3A 20 18		;Pull string position pointer in from memory
1812	DEC A		3D			;Decrease text string pointer
1813	LD &1820, A	32 20 18		;Save it in memory
1816	JZ &1800	CA 00 18		;If Text string pointer is zero redo from start
1819	DEC IX		DD 2B			;If not, Decrease register pointer IX
181B	JP &1809	C3 09 18		;Move to next character

181E	NOP		00			;Gap
181F	NOP		00			;Gap
1820	SCRATCH MEMORY	00			;Text string position pointer

1821	LD A, 15	3E 15			;Speed of scroll multiplier- secondary loop (loop multiplier)
1823	LD B, A		47			;Load value into register B
1824	LD A, 20	3E 20			;Speed of scroll loop- primary loop counter value
1826	LD C, A		4F			;Load that value into register C. Loop will operate B*C times. One loop of C is appx 0.1s.

1827	CALL &1832	CD 32 18		;Call the primary loop code to slow the output down.
182A	DEC C		0D			;Decrease multiplier counter one time.
182B	JNZ &182A	C2 2A 18		;Repeat calling the primary loop until multiplier reaches zero.
182E	CALL &0624	CD 24 06		;Call Display routine again because loop code kills screen
1831	RET		C9			;Return

1832	XTHL		E3			;Stack Exchange HL-HL'  (Primary loop starts here)
1833	XTHL		E3			;Stack Exchange HL-HL'
1834	DEC B		05			;Decrease loop counter by one
1835	CALL &0624	CD 24 06		;Call Display routine because XTHL kills screen
1838    JNZ &1832	C2 32 18		;Loop until loop counter reaches zero
183B	RET		C9			;Return

183C	TEXT 		00			;Space
			00			;Space
			00			;Space
			00			;Space
			00			;Space
			00			;Space
			50			;!
			B3			;D
			85			;L
			03			;R
			BD			;O
			85			;L
			85			;L
			8F			;E
			37			;H
184B			00			;Space
			00			;Space
			00			;Space
			00			;Space
			00			;Space
1850			00			;Space

The Starts At position is far right memory location minus six empty spaces unless you want the screen to begin with text on. Calculate the number of characters you have and put that in as Length of Text String. IX is shifted down through memory locations, which displays the "window" of 6 characters.

Segment Calculator

From the Users Guide:- the Text data can be created using this- pick the segments, allocate them a 1 in the bitwise table, calculate the value in hex and insert it in memory for it to display.

Multitech MPF-1P (w/ VFD)

At first glance, this appears to be a very similar system to the Multitech above, but not only is the code pretty dramatically different, the hardware has some pretty dramatic differences as well, most notably, this one has a gorgeous Vacuum Fluorescent Display! The code does lean on system calls, so it is an interesting contrast to the MPF-1 shown above, which appears to be a bit more bare metal.

Code:

  CALL  CLEAR  | F000: CD B9 09    | Clear Display
  LD HL,TXT    | F003: 21 14 F0    | Load pointer to text data to HL register
  CALL  MSG    | F006: CD CA 09    | Write text at HL pointer until Carriage-Return
  LD IX,DISPBF | F009: DD 21 2C FF | Load pointer to display buffer into IX register
  CALL  SCAN   | F00E: CD 46 02    | Wait for the user to press a key
  JP    PRI_MPF| F011: C3 00 00    | Jump back to the start of the monitor
TXT:           | F014: 48 45 4C 4C | 'HELLORLD!' and a CR in ASCII
  'HELLORLD!\N'| F018: 4F 52 4C 44 | 
               | F01C: 21 0D       | 

PROFI-5/50 E

The PROFI series of computer trainers is an interesting German made trainer based around either an 8080A or 8085A. This particular PROFI-5/50E is an 8085A machine clocked at I believe 6MHz with 8k ROM and 2k RAM. Interestingly, it has full serial capability and has a Centronics interface, but the Intersil chip, which I initially thought was the UART is actually a mega-rare 7-segment driver IC! It's a quite capable little machine and looks primed and ready to be expanded into a full-fledged computer, but in it's base state with the built in keyboard and 7-segment displays, it's the perfect trainer for "Hellorld!"

Code:

8000 01 00 83
8003 CD 60 03
8006 76

8300 76 79 38
8303 38 3F 50
8306 38 5E

Protec Microsystems PRO-83

The Protect Microsystems PRO-80 was released in 1981 and in 1983 was updated to the PRO-83. Finding information on this trainer is very difficult indeed as it was quite rare. The PRO-80 featured a Z80 microprocessor, 1KB of RAM (expandable up to 2KB), 1KB EPROM with the memory monitor, 2 parallel I/O ports, audio cassette interface, 16-key Hex with 8 additional keys, and a 6-position Hex display. The PRO-83 is very similar indeed, using the same display, keyboard, processor, etc.

The big question though - can it Hellorld? You bet it can!

Check a video of it running here.

Code:

[1000] 21 33 10     Start:        LD    HL, Data                ; Point at the start of our string 
[1003] 06 0e                      LD    B, $0E                  ; Number of times to scroll before restarting 
[1005] c5           ScrollLoop:   PUSH  BC                      ; Preserve the scroll counter
[1006] 06 10                      LD    B, $10                  ; Number of times to redraw the display before scrolling 
[1008] c5           DrawAllChars: PUSH  BC                      ; Preserve the redraw counter 
[1009] 06 06                      LD    B, $06                  ; Increment the character pointer by 6 
[100b] 23                         INC   HL                      ;  (cont.) 
[100c] 10 fd                      DJNZ  $ - 1                   ;  (cont.) 
[100e] 3e fe                      LD    A, $FE                  ; Start with the right-most character 
[1010] 06 06                      LD    B, $06                  ; Iterate 6 times 
[1012] d3 48        DrawNextChar: OUT   ($48), A                ; Set enable the character 
[1014] f5                         PUSH  AF                      ; Preserve the character mask 
[1015] 7e                         LD    A, (HL)                 ; Load the character data 
[1016] d3 4c                      OUT   ($4C), A                ; Output the character data 
[1018] c5                         PUSH  BC                      ; Preserve the character counter 
[1019] 06 00                      LD    B, $00                  ; Set up a delay counter 
[101b] 10 fe                      DJNZ  $                       ; Delay here while the display is on 
[101d] c1                         POP   BC                      ; Restore the character counter 
[101e] 3e 00                      LD    A, $00                  ; Load a blank character 
[1020] d3 4c                      OUT   ($4C), A                ; Clear the current character 
[1022] f1                         POP   AF                      ; Restore the character mask 
[1023] 07                         RLCA                          ; Shift to the next character to the left  
[1024] 2b                         DEC   HL                      ; Decrement the character pointer 
[1025] 10 eb                      DJNZ  DrawNextChar            ; Do it again. 
[1027] c1                         POP   BC                      ; Restore the redraw counter 
[1028] 10 de                      DJNZ  DrawAllChars            ; Go back to redraw the display 
[102a] c1                         POP   BC                      ; Restore the scroll counter
[102b] 05                         DEC   B                       ; Decrement the scroll counter 
[102c] ca 00 10                   JP    Z, Start                ; Done scrolling? Start over! 
[102f] 23                         INC   HL                      ; Otherwise, increment the character pointer 
[1030] c3 05 10                   JP    ScrollLoop              ; And do it all again 

[1033] 00           Data:         DB 0x00                       ; Blank 
[1034] 00                         DB 0x00                       ; Blank 
[1035] 00                         DB 0x00                       ; Blank 
[1036] 00                         DB 0x00                       ; Blank 
[1037] 00                         DB 0x00                       ; Blank 
[1038] 00                         DB 0x00                       ; Blank 
[1039] 76                         DB 0x76                       ; H 
[103a] 79                         DB 0x79                       ; E 
[103b] 38                         DB 0x38                       ; L 
[103c] 38                         DB 0x38                       ; L 
[103d] 3f                         DB 0x3F                       ; O 
[103e] 50                         DB 0x50                       ; r 
[103f] 38                         DB 0x38                       ; L 
[1040] 5e                         DB 0x5E                       ; d 
[1041] 00                         DB 0x00                       ; Blank 
[1042] 00                         DB 0x00                       ; Blank 
[1043] 00                         DB 0x00                       ; Blank 
[1044] 00                         DB 0x00                       ; Blank 
[1045] 00                         DB 0x00                       ; Blank 
[1046] 00                         DB 0x00                       ; Blank 

RCA VIP

The RCA 1802 Microprocessor was introduced in the 1970's and gave rise to host of homebrew designs. The most notable was the COSMAC ELF. RCA produced a single board microprocessor system, RCA VIP, that allowed for small programming experiments in machine language and an interpretive virtual machine, Chip-8.

Looking for a unique system to implement "Hellorld", I (Mike A) realized that my 40 year old VIP + Chip-8 would make for an interesting choice. The VIP video out is pretty simple, 64 x 32 pixels (big chonkers!), and no pre-defined character set. All the characters must be part of the program, and drawn as sprites. The "Enterprise" was a canonical image for 1802 systems of the era, so I thought it would be appropriate to include.

Micro setup The display

The program (Chip-8) is written in a fairly standard assembly like form. I needed to whip up my own assembler, as I didn't like any of the multitudes available! The following is an assembler listing, but the raw hex dump follows the listing.

Code:

0x200 00e0  cls

0x202 6003  ld V0,3
0x204 6102  ld V1,2
0x206 6206  ld V2,6

0x208 a264  ld I,H
0x20a d017  drw V0,V1,7

0x20c 8024  add V0,V2
0x20e a26b  ld I,E
0x210 d017  drw V0,V1,7

0x212 8024  add V0,V2
0x214 a272  ld I,L
0x216 d017  drw V0,V1,7

0x218 8024  add V0,V2
0x21a a272  ld I,L
0x21c d017  drw V0,V1,7

0x21e 8024  add V0,V2
0x220 a279  ld I,O
0x222 d017  drw V0,V1,7

0x224 8024  add V0,V2
0x226 a280  ld I,R
0x228 d017  drw V0,V1,7

0x22a 8024  add V0,V2
0x22c a272  ld I,L
0x22e d017  drw V0,V1,7

0x230 8024  add V0,V2
0x232 a287  ld I,D
0x234 d017  drw V0,V1,7

0x236 8024  add V0,V2
0x238 a28e  ld I,BANG
0x23a d017  drw V0,V1,7

0x23c   #
0x23c 6000  ld V0,0
0x23e 610c  ld V1,12
0x240 6214  ld V2,20

0x242 a295  ld I,C1T
0x244 2256  call DRWCOL
0x246 2256  call DRWCOL
0x248 2256  call DRWCOL
0x24a 2256  call DRWCOL
0x24c 2256  call DRWCOL
0x24e 2256  call DRWCOL
0x250 2256  call DRWCOL
0x252 2256  call DRWCOL

0x254 1254 X: jp X

0x256 d018  drwcol: drw V0,V1,8
0x258 6308  ld V3,8
0x25a f31e  add I,V3
0x25c d028  drw V0,V2,8
0x25e f31e  add I,V3
0x260 7008  add V0,8
0x262 00ee  ret

0x264 1111111f111111 H: byte 0X11,0X11,0X11,0X1F,0X11,0X11,0X11
0x26b 00000e111f100f E: byte 0X00,0X00,0X0E,0X11,0X1F,0X10,0X0F
0x272 0c040404040404 L: byte 0X0C,0X04,0X04,0X04,0X04,0X04,0X04
0x279 00000e1111110e O: byte 0X00,0X00,0X0E,0X11,0X11,0X11,0X0E
0x280 00001619101010 R: byte 0X00,0X00,0X16,0X19,0X10,0X10,0X10
0x287 01010107090907 D: byte 0X01,0X01,0X01,0X07,0X09,0X09,0X07
0x28e 04040404040004 BANG: byte 0X04,0X04,0X04,0X04,0X04,0X00,0X04

0x295 000000007f407f00 C1T: byte 0X00,0X00,0X00,0X00,0X7F,0X40,0X7F,0X00
0x29d 0000000000000000 C1B: byte 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00
0x2a5 0000067fc00fc03f C2T: byte 0X00,0X00,0X06,0X7F,0XC0,0X0F,0XC0,0X3F
0x2ad 0f00000000000000 C2B: byte 0X0F,0X00,0X00,0X00,0X00,0X00,0X00,0X00
0x2b5 000000e03f003fd0 C3T: byte 0X00,0X00,0X00,0XE0,0X3F,0X00,0X3F,0XD0
0x2bd 0807183073301807 C3B: byte 0X08,0X07,0X18,0X30,0X73,0X30,0X18,0X07
0x2c5 00000101e010e040 C4T: byte 0X00,0X00,0X01,0X01,0XE0,0X10,0XE0,0X40
0x2cd 20907f00fc000ff0 C4B: byte 0X20,0X90,0X7F,0X00,0XFC,0X00,0X0F,0XF0
0x2d5 00ff0000fc040404 C5T: byte 0X00,0XFF,0X00,0X00,0XFC,0X04,0X04,0X04
0x2dd 0404fc00003fc000 C5B: byte 0X04,0X04,0XFC,0X00,0X00,0X3F,0XC0,0X00
0x2e5 00ff0000ff808080 C6T: byte 0X00,0XFF,0X00,0X00,0XFF,0X80,0X80,0X80
0x2ed 8080f01010f00000 C6B: byte 0X80,0X80,0XF0,0X10,0X10,0XF0,0X00,0X00
0x2f5 07ff0000ff000000 C7T: byte 0X07,0XFF,0X00,0X00,0XFF,0X00,0X00,0X00
0x2fd 0000000000000000 C7B: byte 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00
0x305 e0ff0102fe000000 C8T: byte 0XE0,0XFF,0X01,0X02,0XFE,0X00,0X00,0X00
0x30d 0000000000000000 C8B: byte 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00

0x315 00  end

Code:

200: 00 e0 60 03 61 02 62 06
208: a2 64 d0 17 80 24 a2 6b
210: d0 17 80 24 a2 72 d0 17
218: 80 24 a2 72 d0 17 80 24
220: a2 79 d0 17 80 24 a2 80
228: d0 17 80 24 a2 72 d0 17
230: 80 24 a2 87 d0 17 80 24
238: a2 8e d0 17 60 00 61 0c
240: 62 14 a2 95 22 56 22 56
248: 22 56 22 56 22 56 22 56
250: 22 56 22 56 12 54 d0 18
258: 63 08 f3 1e d0 28 f3 1e
260: 70 08 00 ee 11 11 11 1f
268: 11 11 11 00 00 0e 11 1f
270: 10 0f 0c 04 04 04 04 04
278: 04 00 00 0e 11 11 11 0e
280: 00 00 16 19 10 10 10 01
288: 01 01 07 09 09 07 04 04
290: 04 04 04 00 04 00 00 00
298: 00 7f 40 7f 00 00 00 00
2a0: 00 00 00 00 00 00 00 06
2a8: 7f c0 0f c0 3f 0f 00 00
2b0: 00 00 00 00 00 00 00 00
2b8: e0 3f 00 3f d0 08 07 18
2c0: 30 73 30 18 07 00 00 01
2c8: 01 e0 10 e0 40 20 90 7f
2d0: 00 fc 00 0f f0 00 ff 00
2d8: 00 fc 04 04 04 04 04 fc
2e0: 00 00 3f c0 00 00 ff 00
2e8: 00 ff 80 80 80 80 80 f0
2f0: 10 10 f0 00 00 07 ff 00
2f8: 00 ff 00 00 00 00 00 00
300: 00 00 00 00 00 e0 ff 01
308: 02 fe 00 00 00 00 00 00
310: 00 00 00 00 00 00

NEC TK-80/TK-85

The NEC TK-80 is a trainer board using the NEC μCOM-80 (μPD8080A), a CPU that was (mostly) compatible with the Intel 8080A. Released in 1976, it was one of the first microprocessor systems easily available to the public in Japan and, though developed for engineers considering using the μCOM-80 in their products, became immensely popular with hobbyists who could afford neither more expensive systems nor the terminals that they usually required. The TK-85, released in 1980, was essentially the same but with an 8085-compatible μPD8085AC processor.

The following program is TK-80/85 Hello Program from the TK-80/TK-85 Reverse Engineering repo.

8000: 21 12 80 11 F8 83 7E B7
8008: C2 0C 80 76 12 23 13 C3
8010: 06 80 76 79 38 38 3F 50
8018: 38 5E 00