Paolo Amoroso's Journal

Assembly

Encouraged by the emuStudio developer, I donated to the project an Intel 8080 Assembly demo. It's a modified version of Twirl, my program to display a twirling bar animation.

Here's the code I contributed:

; Twirling bar animation by Paolo Amoroso <info@paoloamoroso.com>
;
; Runs on an Altair 8800 with an ADM-3A terminal. Press any key
; to interrupt the program.


FRAMES    equ  8              ; Number of animation frames

CLS       equ  1ah            ; ADM-3A escape sequence
HOME      equ  1eh            ; ADM-3A escape sequence
STATUS    equ  10h            ; Input status port
READY     equ  1              ; Character ready status mask


          mvi  a, CLS         ; Clear screen
          call putchar

loop:     lxi  h, ANIM        ; Initialize frame pointer...
          mvi  b, FRAMES      ; ...and count

loop1:    mvi  a, HOME        ; Go to home
          call putchar

          mov  a, m           ; Print current frame
          call putchar

          push psw
          in   STATUS
          ani  READY          ; Key pressed?
          jnz  exit           ; Yes
          pop  psw

          inx  h
          dcr  b
          jnz  loop1

          jmp  loop


exit:     pop psw             ; Clear psw left on stack
          hlt


ANIM:     db   '|/-\|/-\'     ; 8 frames


include	'include\putchar.inc'

Unlike the original code, which I designed to run on emuStudio and be easy to port to CP/M, this new version is intended to run only on emuStudio. This was an occasion to simplify the code.

The main difference is the escape codes for VT100-compatible terminals on CP/M are strings, whereas the ADM-3A codes Twirl sends on emuStudio are single bytes. This allows the program to print the codes with the putchar library subroutine instead of putstr. Doing away with putstr no longer requires saving and restoring the HL register pair in the calling sequences.

Finally, I added code to terminate the program if a key is pressed.

#intel8080 #Assembly

Discuss... Email | Reply @amoroso@fosstodon.org

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.

Motivation

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

                hlt


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


include 'include\putstr.inc'
include 'include\putchar.inc'

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 @amoroso@fosstodon.org