Paolo Amoroso's Journal


I wrote Twirl, an Intel 8080 Assembly program that displays the ASCII animation of a bar twirling at the home position of the terminal screen. To make things a bit more clear I recorded a screencast to show the running program and what the animation looks like.


I developed this short program as an Assembly learning exercise related to Suite8080, a suite of Intel 8080 Assembly cross-development tools in Python I'm working on. The project, which is a lot of fun, drove me down a rabbit hole of Intel 8080 Assembly, CP/M, and retrocomputing.

I additionally wanted to explore the emuStudio execution environment and get the algorithm working. Now that it does, I can port Twirl to CP/M and add the program to Suite8080 as an Assembly demo.

The execution environment

Twirl runs on a virtual Altair 8800 computer in emuStudio, a beautiful emulator and Assembly development environment that can recreate a number of classic computers and CPUs.

I designed Twirl to run on a bare Altair 8800 connected to a Lear Siegler ADM-3A terminal. Any amount of RAM will do as the assembled code is only a few dozen bytes long. In the execution environment there's no host operating system or resident monitor, just a few basic character I/O subroutines emuStudio ships with.

Once started, Twirl runs an infinite animation loop. To terminate it I click the emuStudio Stop emulation button.

By default the Altair 8800 runs at 2 Mhz in emuStudio, which causes some terminal flicker when executing Twirl. That's why I usually set the CPU frequency to 4 MHz, closer to that of late CP/M computers.

The code

Here's the source code of Twirl:

; twirl.asm
; Twirling bar animation
; Runs in emuStudio emulating an Altair 8800 with an
; ADM-3A terminal

FRAMES          equ     8               ; Number of animation frames

                push    h
                lxi     h, CLS
                call    putstr          ; Clear screen
                pop     h

loop:           lxi     h, ANIM
                mvi     b, FRAMES

loop1:          push    h
                lxi     h, HOME
                call    putstr          ; Go to home
                pop     h

                mov     a, m
                push    h
                call    putchar         ; Print current frame
                pop     h

                inx     h
                dcr     b
                jnz     loop1

                jmp     loop


CLS:            db      1ah, 0          ; ADM-3A escape sequence
HOME:           db      1eh, 0          ; ADM-3A escape sequence
ANIM:           db      '|/-\|/-\'      ; 8 frames

include 'include\'
include 'include\'

After clearing the screen, the program starts an infinite loop that repeats going through each frame of the animation, moving the cursor to the home position, and printing the current frame. The animation consists of a byte array containing the sequence of characters — frames — to display.

Some data definitions follow, i.e. the ADM-3A escape sequences to clear the screen and go to home, as well as the animation array.

The program ends with include directives for importing the following I/O subroutines:

  • putstr: prints to the terminal the 0-terminated string pointed to by the HL register pair
  • putchar: prints to the terminal the character in register A

The calls are enclosed in code that saves and restores the registers the subroutines overwrite.

Future work

What does it take to port Twirl to CP/M?

I use z80pack as my main CP/M emulator, so I design the Suite8080 demos to run on a machine with a VT100 or compatible terminal like the CP/M systems z80pack emulates.

I'll begin by converting the terminal escape codes from ADM-3A to VT100. Next, I'll replace the subroutine calls to equivalent BDOS calls. Finally, I want to support terminating the program by pressing any key. This will require code to check the console status for key presses.

#intel8080 #Assembly

Discuss... Email | Reply