Bernd Ulmann
Published © CC BY

The Z80_mini

A really tiny Z80 based computer.

IntermediateFull instructions provided8 hours1,304
The Z80_mini

Things used in this project

Hardware components

Capacitor 10 µF
Capacitor 10 µF
×1

Story

Read more

Code

Code snippet #4

Plain text
0000:           N8VEM           equ     0               ; If set to 1, the monitor is built
0000:                                                   ; for the N8VEM, otherwise, the
0000:                                                   ; old homebrew Z80 computer is targeted.
0000:           FEATURE_BASIC   equ     0               ; If set to 0, the BASIC interpreter
0000:                                                   ; will not be included.
0000:           ;******************************************************************************
0000:           ;
0000:           ;  Small monitor for the Z80 single board computer consisting of 32 kB ROM 
0000:           ; ($0000 to $ffff), 32 kB RAM ($8000 to $ffff) and a 16c550 UART.
0000:           ;
0000:           ; B. Ulmann, 28-SEP-2011, 29-SEP-2011, 01-OCT-2011, 02-OCT-2011, 30-OCT-2011,
0000:           ;            01-NOV-2011, 02-NOV-2011, 03-NOV-2011, 06/07/08-JAN-2012
0000:           ; I. Kloeckl, 06/07/08-JAN-2012 (FAT implementation for reading files)
0000:           ; B. Ulmann, 14-JAN-2011 
0000:           ;
0000:           ; 07-MAR-2012: Fabio Zanicotti spotted an error in the ide_get_id-routine - 
0000:           ;              the value $0a should have been written to ide_lba3 but was
0000:           ;              instead written into ide_status_cmd (I am quite puzzled why
0000:           ;              the routine worked nevertheless). This has been corrected. :-)
0000:           ;
0000:           ; B. Ulmann, 20-MAY-2012 port to N8VEM - no IDE support at the moment
0000:           ;            27-MAY-2012 PPIDE support for N8VEM
0000:           ;            29-MAY-2012 New system call uart_status introduced (used by the
0000:           ;                        4th interpreter)
0000:           ;            01-JUN-2012 CTRL-Y introduced
0000:           ;            03-JUN-2012 F/R command added, UART initialization changed
0000:           ;            06-JUN-2012 CAMEL-Forth added
0000:           ;            07-JUN-2012 Minor bug fixes (load routine), added rom2ram
0000:           ;            16-JUN-2012 stroup added, CAMEL Forth modified to use gets etc.
0000:           ;            12-MAY-2013 Added support for the old homebrew Z80 computer.
0000:           ;            20-MAY-2013 Added BASIC-subsystem.
0000:           ;            05-JUN-2013 Added John Kerr's Z80 disassembler.
0000:           ;            28-JUN-2013 Removed BASIC-support for the Z80mini
0000:           ;
0000:           ; Version 0.14a
0000:           ;
0000:           ;******************************************************************************
0000:           ;
0000:           ; TODO: 
0000:           ;       Read and print IDE error status codes in case of error!
0000:           ;
0000:           ; Known issues:
0000:           ;       Memory Dump has a problem when the end address is >= FF00
0000:           ;
0000:           ;******************************************************************************
0000:           ;
0000:           ;  RST $00 will enter the monitor (do not care about the return address pushed
0000:           ; onto the stack - the stack pointer will be reinitialized during cold as well
0000:           ; as during warm starts.
0000:           ;
0000:           ;  Monitor routines will generally called by placing the necessary parameters
0000:           ; into some processor registers and then issuing RST $08. More about this later.
0000:           ;
0000:           ;  Whenever a call to the system routine getc is issued, it is tested if the
0000:           ; character entered was a CTRL-Y (like in VMS :-) ). If so, a restart of the
0000:           ; monitor takes place. Although this interrupt possibility requires a running
0000:           ; program to call getc from time to time it is better than nothing since the
0000:           ; monitor currently does not take care of interrupts at all.
0000:           ;
0000:           ;  Programs running in memory should not make use of memory above about $FB00 
0000:           ; to leave some space for the monitor stack.
0000:           ;
0000:           ;  Memory layout is as follows:
0000:           ;
0000:           ;  +-------+
0000:           ;  ! $FFFF !    General purpose 512 byte buffer
0000:           ;  !  ---  !
0000:           ;  ! $FE00 !
0000:           ;  +-------+
0000:           ;  ! $DFFF !    FAT control block
0000:           ;  !  ---  !
0000:           ;  ! $FDDC !
0000:           ;  +-------+
0000:           ;  ! $FDDB !    File control block
0000:           ;  !  ---  !
0000:           ;  ! $FBBE !
0000:           ;  +-------+
0000:           ;  ! $FBBD !    81 byte string buffer
0000:           ;  !  ---  !
0000:           ;  ! $FB6D !
0000:           ;  +-------+
0000:           ;  ! $FB6C !    12 byte string buffer
0000:           ;  !  ---  !
0000:           ;  ! $FB61 !
0000:           ;  +-------+
0000:           ;  ! $FB60 !    Buffers for various routines
0000:           ;  !  ---  !
0000:           ;  ! $FB4D !
0000:           ;  +-------+
0000:           ;  ! $FB4C !    Scratch area (16 bytes)
0000:           ;  !  ---  !
0000:           ;  ! $FB3D !
0000:           ;  +-------+
0000:           ;  ! $FB3C !    Cold/warm start control (1 byte)
0000:           ;  +-------+
0000:           ;  ! $FB3B !    Stack
0000:           ;  !  ...  !
0000:           ;  ! $8000 !    Begin of RAM
0000:           ;  +-------+
0000:           ;  ! $7FFF !    ROM area
0000:           ;  !  ---  !    RST $08 calls a system routine
0000:           ;  ! $0000 !    RST $00 restarts the monitor
0000:           ;  +-------+
0000:           ;
0000:           ;
0000:           LOADABLE        equ     0               ; This is necessary for the built-in
0000:                                                   ; Forth-interpreter to work in ROM.
0000:           monitor_start   equ     $0000           ; $0000 -> ROM, $8000 -> Test image
0000:           #target	rom		; ((inserted by zasm))
0000:           #code	0,$10000	; ((inserted by zasm))
0000:                           org     monitor_start
0000:           ;
0000:           ;  Definitions used by the monitor and all programs based on this monitor.
0000:           ;
0000:           ; 01-JUN-2013   B. Ulmann   1st implementation
0000:           ;
0000:           rom_start       equ     $0
0000:           rom_end         equ     $7fff
0000:           ram_start       equ     $8000
0000:           ram_end         equ     $ffff
0000:           buffer          equ     ram_end - $1ff  ; 512 byte IDE general purpose buffer
0000:           last_user_ram   equ     $f9ff
0000:           ;
0000:           ; Define the FAT control block memory addresses:
0000:           ;
0000:           datastart       equ     buffer - 4      ; Data area start vector
0000:           rootstart       equ     datastart - 4   ; Root directory start vector
0000:           fat1start       equ     rootstart - 4   ; Start vector to first FAT
0000:           psiz            equ     fat1start - 4   ; Size of partition (in sectors)
0000:           pstart          equ     psiz - 4        ; First sector of partition
0000:           rootlen         equ     pstart - 2      ; Maximum number of entries in directory
0000:           fatsec          equ     rootlen - 2     ; FAT size in sectors
0000:           ressec          equ     fatsec - 2      ; Number of reserved sectors
0000:           clusiz          equ     ressec - 1      ; Size of a cluster (in sectors)
0000:           fatname         equ     clusiz - 9      ; Name of the FAT (null terminated)
0000:           fatcb           equ     fatname         ; Start of the FATCB
0000:           ;
0000:           ; Define a file control block (FCB) memory addresses and displacements:
0000:           ;
0000:           file_buffer     equ     fatcb - $200            ; 512 byte sector buffer
0000:           cluster_sector  equ     file_buffer - 1         ; Current sector in cluster
0000:           current_sector  equ     cluster_sector - 4      ; Current sector address
0000:           current_cluster equ     current_sector - 2      ; Current cluster number
0000:           file_pointer    equ     current_cluster - 4     ; Pointer for file position
0000:           file_type       equ     file_pointer - 1        ; 0 -> not found, else OK
0000:           first_cluster   equ     file_type - 2           ; First cluster of file
0000:           file_size       equ     first_cluster - 4       ; Size of file
0000:           file_name       equ     file_size - 12          ; Canonical name of file
0000:           fcb             equ     file_name               ; Start of the FCB
0000:           ;
0000:           fcb_filename            equ     0
0000:           fcb_file_size           equ     $c
0000:           fcb_first_cluster       equ     $10
0000:           fcb_file_type           equ     $12
0000:           fcb_file_pointer        equ     $13
0000:           fcb_current_cluster     equ     $17
0000:           fcb_current_sector      equ     $19
0000:           fcb_cluster_sector      equ     $1d
0000:           fcb_file_buffer         equ     $1e
0000:           ;
0000:           ; We also need some general purpose string buffers:
0000:           ;
0000:           string_81_bfr   equ     fcb - 81
0000:           string_12_bfr   equ     string_81_bfr - 12
0000:           ;
0000:           ;  A number of routines need a bit of scratch RAM, too. Since these are 
0000:           ; sometimes interdependent, each routine gets its own memory cells (only
0000:           ; possible since the routines are not recursively called).
0000:           ;
0000:           load_file_scrat equ     string_12_bfr - 2       ; Two bytes for load_file
0000:           str2filename_de equ     load_file_scrat - 2     ; Two bytes for str2filename
0000:           fopen_eob       equ     str2filename_de - 2     ; Eight bytes for fopen
0000:           fopen_rsc       equ     fopen_eob - 4
0000:           fopen_scr       equ     fopen_rsc - 2
0000:           dirlist_scratch equ     fopen_scr - 2           ; Eight bytes for fopen
0000:           dirlist_eob     equ     dirlist_scratch - 2
0000:           dirlist_rootsec equ     dirlist_eob - 4
0000:           scratch_area    equ     dirlist_rootsec - $1    ; Scratch memory (16 byte)
0000:           ;
0000:           start_type      equ     scratch_area  - $10    ; Distinguish cold/warm start
0000:           ;
0000:           ;  System calls are implemented by rst08 which expects the number of the
0000:           ; call to be executed in ix. The numbers of valid calls are defined here:
0000:           ;
0000:           _cold_start     equ     $0
0000:           _is_hex         equ     $1
0000:           _is_print       equ     $2
0000:           _to_upper       equ     $3
0000:           _crlf           equ     $4
0000:           _getc           equ     $5
0000:           _putc           equ     $6
0000:           _puts           equ     $7
0000:           _strcmp         equ     $8
0000:           _gets           equ     $9
0000:           _fgetc          equ     $a
0000:           _dump_fcb       equ     $b
0000:           _fopen          equ     $c
0000:           _dirlist        equ     $d
0000:           _fatmount       equ     $e
0000:           _fatunmount     equ     $f
0000:           _strchr         equ     $10
0000:           _uart_status    equ     $11
0000:           _getc_nowait    equ     $12
0000:           _print_word     equ     $13
0000:           _print_byte     equ     $14
0000:           _stroup         equ     $15
0000:           _get_word       equ     $16
0000:           ;
0000:           ; Some useful ASCII (control) characters:
0000:           ;
0000:           eos             equ     $00             ; End of string
0000:           cr              equ     $0d             ; Carriage return
0000:           lf              equ     $0a             ; Line feed
0000:           space           equ     $20             ; Space
0000:           tab             equ     $09             ; Tabulator
0000:           bs              equ     $08             ; Backspace
0000:           bel             equ     $07             ; Bell
0000:           ctrl_y          equ     25              ; CTRL-Y character
0000:           
0000:           #include        "mondef.asm"
0000:           ;
0000:           #if N8VEM = 1
0000:           ;
0000:           ; 82C55 registers (the 82C55 is used to implement a simple IDE interface):
0000:           ;
0000:           reg_ppi_base    equ     $60                     ; 82C55 base address
0000:           reg_ppi_cntl    equ     reg_ppi_base + 3        ; 82C55 control register
0000:           ;
0000:           reg_ppide_lsb   equ     reg_ppi_base + 0        ; 82C55 port A
0000:           reg_ppide_msb   equ     reg_ppi_base + 1        ; 82C55 port B
0000:           reg_ppide_cntl  equ     reg_ppi_base + 2        ; 82C55 port C
0000:           #else
0000:           ide_base        equ     $10
0000:           #endif                                          ; N8VEM = 1?
0000:           ;
0000:           ; 16C550 registers:
0000:           ;
0000:           #if N8VEM = 1
0000:           uart_base       equ     $68
0000:           #else
0000:           uart_base       equ     $0
0000:           #endif
0000:           ;
0000:           uart_register_0 equ     uart_base + 0           ; Read/write a character
0000:           uart_register_1 equ     uart_base + 1
0000:           uart_register_2 equ     uart_base + 2
0000:           uart_register_3 equ     uart_base + 3
0000:           uart_register_4 equ     uart_base + 4
0000:           uart_register_5 equ     uart_base + 5           ; RX/TX status
0000:           uart_register_6 equ     uart_base + 6
0000:           uart_register_7 equ     uart_base + 7
0000:           ;
0000:           #if N8VEM = 1
0000:           ;
0000:           ; Memory Page Configuration Latches:
0000:           ;
0000:           mpcl_ram        equ     $78
0000:           mpcl_rom        equ     $7c
0000:           ;
0000:           #endif
0000:           ;
0000:           ; Main entry point (RST 00H):
0000:           ;
0000: F3        rst_00          di                      ; Disable interrupts 
0001:           ;
0001:           ;  The stackpointer will be predecremented by a push instruction. Therefore
0001:           ; we set the start of the stack to the end of the reserved memory area in 
0001:           ; high memory.
0001:           ;
0001: 313BFB                    ld      sp, start_type - $1
0004: 1817                      jr      initialize      ; Jump over the RST-area
0006:           ;
0006:           ;  RST-area - here is the main entry point into the monitor. The calling 
0006:           ; standard looks like this:
0006:           ;
0006:           ; 1) Set register IX to the number of the system routine to be called.
0006:           ; 2) Set the remaining registers according to the routine's documentation.
0006:           ; 3) Execute RST $08 to actually call the system routine.
0006:           ; 4) Evaluate the values returned in the registers as described by the 
0006:           ;    Routine's documentation. 
0006:           ;
0006:           ;  (Currently there are no plans to use more RST entry points, so this routine
0006:           ; just runs as long as necessary in memory. If more RSTs will be used, this
0006:           ; routine should to be moved to the end of the used ROM area with only a 
0006:           ; simple jump at the RST $08-location.)
0006:           ;
0006:           ;  This technique of calling system routines can be used as the following
0006:           ; example program that just echos characters read from the serial line
0006:           ; demonstrates:
0006:           ;
0006:           ;         org     $8000           ; Start in lower RAM
0006:           ; loop    ld      ix, 5           ; Prepare call to getc
0006:           ;         rst     08              ; Execute getc
0006:           ;         cp      3               ; CTRL-C pressed?
0006:           ;         jr      z, exit         ; Yes - exit
0006:           ;         ld      ix, 6           ; Prepare call to putc
0006:           ;         rst     08              ; Execute putx
0006:           ;         jr      loop            ; Process next character
0006:           ; exit    ld      ix, 4           ; Exit - print a CR/LF pair
0006:           ;         rst     08              ; Call CRLF
0006:           ;         ld      hl, msg         ; Pointer to exit message
0006:           ;         ld      ix, 7           ; Prepare calling puts
0006:           ;         rst     08              ; Call puts
0006:           ;         rst     00              ; Restart monitor (warm start)
0006:           ; msg     defb    "That's all folks.", $d, $a, 0
0006:           ;
0006:           ;  IMPORTANT: The content of ix is destroyed during the call, so it is NOT
0006:           ;             possible to perform successive calls to the same system service
0006:           ;             in a sequence without reloading the ix-register!
0006:           ;
0006:           ;  Currently the following functions are available (a more detailed description
0006:           ; can be found in the dispatch table itself - search for the label 
0006:           ; dispatch_table):
0006:           ;
0006:           ;       $00:    cold_start
0006:           ;       $01:    is_hex
0006:           ;       $02:    is_print
0006:           ;       $03:    to_upper
0006:           ;       $04:    crlf
0006:           ;       $05:    getc
0006:           ;       $06:    putc
0006:           ;       $07:    puts
0006:           ;       $08:    strcmp
0006:           ;       $09:    gets
0006:           ;       $0A:    fgetc
0006:           ;       $0B:    dump_fcb
0006:           ;       $0C:    fopen
0006:           ;       $0D:    dirlist
0006:           ;       $0E:    fatmount
0006:           ;       $0F:    fatunmount
0006:           ;       $10:    strchr
0006:           ;       $11:    uart_status
0006:           ;       $12:    getc_nowait
0006:           ;       $13:    print_word
0006:           ;       $14:    print_byte
0006:           ;       $15:    stroup
0006:           ;       $16:    get_word
0006:           ;
0006:           ;               org     monitor_start + $08
0006: 00                        nop                     ; Beware: zasm is buggy concerning
0007: 00                        nop                     ; ORG. Therefore we need two nops to
0008:                                                   ; get to address $0008.
0008: C5        rst_08          push    bc              ; Save bc and hl
0009: E5                        push    hl
000A: DDE5                      push    ix              ; Copy the contents of ix
000C: E1                        pop     hl              ; into hl
000D: 29                        add     hl, hl          ; Double to get displacement in table
000E: 014C1D                    ld      bc, dispatch_table
0011: 09                        add     hl, bc          ; Calculate displacement in table
0012: 4E23462B                  ld      bc, (hl)        ; Load bc with the destination address
0016: C5                        push    bc
0017: DDE1                      pop     ix              ; Load ix with the destination address
0019: E1                        pop     hl              ; Restore hl
001A: C1                        pop     bc              ; and bc
001B: DDE9                      jp      (ix)            ; Jump to the destination routine
001D:           ;
001D:           ; Initialize UART to 9600,8N1:
001D:           ;
001D: 3E80      initialize      ld      a, $80
001F: D303                      out     (uart_register_3), a
0021: 3E0C                      ld      a, $c           ; 1843200 / (16 * 9600)
0023: D300                      out     (uart_register_0), a
0025: AF                        xor     a
0026: D301                      out     (uart_register_1), a
0028: 3E03                      ld      a, $3           ; 8N1
002A: D303                      out     (uart_register_3), a
002C: 3E07                      ld      a, $7           ; FIFO enable, reset RCVR/XMIT FIFO
002E: D302                      out     (uart_register_2), a
0030:           ;
0030:           ; Print welcome message:
0030:           ;
0030: 215A01                    ld      hl, hello_msg
0033: CD4B12                    call    puts
0036:           ;
0036:           ;  If this is a cold start (the location start_type does not contain $aa)
0036:           ; all available RAM will be reset to $00 and a message will be printed.
0036:           ;
0036: 3A3CFB    init_mem        ld      a, (start_type)
0039: FEAA                      cp      $aa             ; Warm start?
003B: 2818                      jr      z, main_loop    ; Yes - enter command loop
003D: 21DA02                    ld      hl, cold_start_msg
0040: CD4B12                    call    puts            ; Print cold start message
0043: 210080                    ld      hl, ram_start   ; Start of block to be filled with $00
0046: 545D                      ld      de, hl          ; End address of block
0048: 13                        inc     de              ; plus 1 (for ldir)
0049: 01FF7F                    ld      bc, ram_end - ram_start
004C: 3600                      ld      (hl), $00       ; Load first memory location
004E: EDB0                      ldir                    ; And copy this value down
0050: 213CFB                    ld      hl, start_type
0053: 36AA                      ld      (hl), $aa       ; Cold start done, remember this
0055:           ;
0055:           ; Read characters from the serial line and interpret them:
0055:           ;
0055: 216202    main_loop       ld      hl, monitor_prompt
0058: CD4B12                    call    puts
005B:           ;
005B:           ; The monitor is rather simple: All commands consist of one or two letters. 
005B:           ; The first character selects a command group, the second the desired command
005B:           ; out of that group. When a command is recognized, it will be spelled out 
005B:           ; automatically and the user will be prompted for arguments if applicable. 
005B:           ;
005B: CDF902                    call    monitor_key     ; Read a key
005E:           ; Which group did we get?
005E: FE43                      cp      'C'             ; Control group?
0060: 2022                      jr      nz, disk_group  ; No - test next group
0062: 216802                    ld      hl, cg_msg      ; Print group prompt
0065: CD4B12                    call    puts
0068: CDF902                    call    monitor_key     ; Get command key
006B: FE43                      cp      'C'             ; Cold start?
006D: CA1C14                    jp      z, cold_start
0070: FE57                      cp      'W'             ; Warm start?
0072: CA2114                    jp      z, warm_start
0075: FE53                      cp      'S'             ; Start?
0077: CAC610                    jp      z, start
007A: FE49                      cp      'I'             ; Info?
007C: CC8B0D                    call    z, info
007F: 28D4                      jr      z, main_loop
0081: C34E01                    jp      cmd_error       ; Unknown control-group-command
0084: FE44      disk_group      cp      'D'             ; Disk group?
0086: 2028                      jr      nz, file_group  ; No - file group?
0088: 217102                    ld      hl, dg_msg      ; Print group prompt
008B: CD4B12                    call    puts
008E: CDF902                    call    monitor_key     ; Get command
0091: FE49                      cp      'I'             ; Info?
0093: CC1B08                    call    z, disk_info
0096: 28BD                      jr      z, main_loop
0098: FE4D                      cp      'M'             ; Mount?
009A: CC7C0F                    call    z, mount
009D: 28B6                      jr      z, main_loop
009F: FE54                      cp      'T'             ; Read from disk?
00A1: CC4708                    call    z, disk_transfer
00A4: 28AF                      jr      z, main_loop
00A6: FE55                      cp      'U'             ; Unmount?
00A8: CCE010                    call    z, unmount
00AB: 28A8                      jr      z, main_loop
00AD: C34E01                    jp      cmd_error       ; Unknown disk-group-command
00B0: FE46      file_group      cp      'F'             ; File group?
00B2: 2028                      jr      nz, help_group  ; No - help group?
00B4: 217702                    ld      hl, fg_msg      ; Print group prompt
00B7: CD4B12                    call    puts
00BA: CDF902                    call    monitor_key     ; Get command
00BD: FE43                      cp      'C'             ; Cat?
00BF: CC0A03                    call    z, cat_file
00C2: 2891                      jr      z, main_loop
00C4: FE44                      cp      'D'             ; Directory?
00C6: CC4903                    call    z, directory
00C9: 288A                      jr      z, main_loop
00CB: FE4C                      cp      'L'             ; Load?
00CD: CCDB0E                    call    z, load_file
00D0: 2883                      jr      z, main_loop
00D2: FE52                      cp      'R'             ; Run an executable?
00D4: CC6A0E                    call    z, load_and_run
00D7: CA5500                    jp      z, main_loop
00DA: 1872                      jr      cmd_error       ; Unknown file-group-command
00DC: FE48      help_group      cp      'H'             ; Help? (No further level expected.)
00DE: CCC40A                    call    z, help         ; Yes :-)
00E1: CA5500                    jp      z, main_loop
00E4: FE4D      memory_group    cp      'M'             ; Memory group?
00E6: C23401                    jp      nz, subsys_group; No - subsystem group?
00E9: 217D02                    ld      hl, mg_msg      ; Print group prompt
00EC: CD4B12                    call    puts
00EF: CDF902                    call    monitor_key     ; Get command key
00F2: FE41                      cp      'A'             ; Disassemble?
00F4: CC6103                    call    z, disassemble
00F7: CA5500                    jp      z, main_loop
00FA: FE44                      cp      'D'             ; Dump?
00FC: CC5409                    call    z, dump
00FF: CA5500                    jp      z, main_loop
0102: FE45                      cp      'E'             ; Examine?
0104: CCCA09                    call    z, examine
0107: CA5500                    jp      z, main_loop
010A: FE46                      cp      'F'             ; Fill?
010C: CC1D0A                    call    z, fill
010F: CA5500                    jp      z, main_loop
0112: FE49                      cp      'I'             ; INTEL-Hex load?
0114: CCD50C                    call    z, ih_load
0117: CA5500                    jp      z, main_loop
011A: FE4C                      cp      'L'             ; Load?
011C: CCA10D                    call    z, load
011F: CA5500                    jp      z, main_loop
0122: FE4D                      cp      'M'             ; Move?
0124: CC920F                    call    z, move
0127: CA5500                    jp      z, main_loop
012A: FE52                      cp      'R'             ; Register dump?
012C: CC0A10                    call    z, rdump
012F: CA5500                    jp      z, main_loop
0132:           #if N8VEM = 1
0132:                           cp      'S'             ; Switch ROM to RAM?
0132:                           call    z, rom2ram      ; This routine won't return
0132:                           jp      z, main_loop
0132:           #endif
0132: 181A                      jr      cmd_error       ; Unknown memory-group-command
0134: FE53      subsys_group    cp      'S'             ; Subsystem group?
0136: C24901                    jp      nz, group_error ; No - print an error message
0139: 218502                    ld      hl, sg_msg      ; Print group prompt
013C: CD4B12                    call    puts
013F: CDF902                    call    monitor_key     ; Get command key
0142: FE46                      cp      'F'             ; Forth?
0144: CA7A1D                    jp      z, forth_subsystem
0147:           #if FEATURE_BASIC = 1
0147:                           cp      'B'             ; BASIC?
0147:                           jp      z, basic_subsystem
0147:           #endif
0147: 1805                      jr      cmd_error       ; Unknown subsytem-group-command
0149: 21B602    group_error     ld      hl, group_err_msg
014C: 1803                      jr      print_error
014E: 219002    cmd_error       ld      hl, command_err_msg
0151: CD4012    print_error     call    putc            ; Echo the illegal character
0154: CD4B12                    call    puts            ; and print the error message
0157: C35500                    jp      main_loop
015A:           ;
015A:           ; Some constants for the monitor:
015A:           ;
015A: 0D0A0D0A
015E: 53696D70
0162: 6C65205A
0166: 38302D6D
016A: 6F6E6974
016E: 6F72202D
0172: 20562030
0176: 2E313461
017A: 20        hello_msg       defb    cr, lf, cr, lf, "Simple Z80-monitor - V 0.14a "
017B: 28422E20
017F: 556C6D61
0183: 6E6E2C20
0187: 53657074
018B: 656D6265
018F: 72203230
0193: 3131202D
0197: 204A756E
019B: 65203230
019F: 3133290D
01A3: 0A                        defb    "(B. Ulmann, September 2011 - June 2013)", cr, lf
01A4: 20202054
01A8: 68697320
01AC: 6D6F6E69
01B0: 746F7220
01B4: 636F6E74
01B8: 61696E73
01BC: 20427261
01C0: 6420526F
01C4: 64726967
01C8: 75657A27
01CC: 20                        defb    "   This monitor contains Brad Rodriguez' "
01CD: 43414D45
01D1: 4C20466F
01D5: 7274682C
01D9: 200D0A                    defb    "CAMEL Forth, ", cr, lf
01DC: 20202020
      ...
01F5: 4A6F686E
01F9: 204B6572
01FD: 72277320
0201: 5A383020                  defb    "                         John Kerr's Z80 "
0205: 64697361
0209: 7373656D
020D: 626C6572                  defb    "disassembler"
0211:           #if FEATURE_BASIC = 1
0211:                           defb    ", and", cr, lf
0211:                           defb    "                         BASIC 4.7 (C) Microsoft"
0211:           #endif
0211: 0D0A                      defb    cr, lf
0213: 2D2D2D2D
      ...
023B:                           defb    "----------------------------------------"
023B: 2D2D2D2D
      ...
0262:                           defb    "---------------------------------------"
0262: 0D0A5A3E
0266: 2000      monitor_prompt  defb    cr, lf, "Z> ", eos
0268: 434F4E54
026C: 524F4C2F
0270: 00        cg_msg          defb    "CONTROL/", eos
0271: 4449534B
0275: 2F00      dg_msg          defb    "DISK/", eos
0277: 46494C45
027B: 2F00      fg_msg          defb    "FILE/", eos
027D: 4D454D4F
0281: 52592F00  mg_msg          defb    "MEMORY/", eos
0285: 53554253
0289: 59535445
028D: 4D2F00    sg_msg          defb    "SUBSYSTEM/", eos
0290: 3A205379
0294: 6E746178
0298: 20657272
029C: 6F72202D
02A0: 20636F6D
02A4: 6D616E64
02A8: 206E6F74
02AC: 20666F75
02B0: 6E64210D
02B4: 0A00      command_err_msg defb    ": Syntax error - command not found!", cr, lf, eos
02B6: 3A205379
02BA: 6E746178
02BE: 20657272
02C2: 6F72202D
02C6: 2067726F
02CA: 7570206E
02CE: 6F742066
02D2: 6F756E64
02D6: 210D0A00  group_err_msg   defb    ": Syntax error - group not found!", cr, lf, eos
02DA: 436F6C64
02DE: 20737461
02E2: 72742C20
02E6: 636C6561
02EA: 72696E67
02EE: 206D656D
02F2: 6F72792E
02F6: 0D0A00    cold_start_msg  defb    "Cold start, clearing memory.", cr, lf, eos
02F9:           ;
02F9:           ;  Read a key for command group and command (this routine differs slightly
02F9:           ; from getc as it can also return to the monitor prompt with a dirty trick
02F9:           ; readjusting the stack):
02F9:           ;
02F9: CD5911    monitor_key     call    getc
02FC: FE0A                      cp      lf              ; Ignore LF
02FE: 28F9                      jr      z, monitor_key  ; Just get the next character
0300: CD4311                    call    to_upper
0303: FE0D                      cp      cr              ; A CR will return to the prompt
0305: C0                        ret     nz              ; No - just return
0306: 33                        inc     sp              ; Correct SP to and avoid ret!
0307: C35500                    jp      main_loop
030A:           ;
030A:           ;******************************************************************************
030A:           ;***
030A:           ;*** The following routines are used in the interactive part of the monitor
030A:           ;***
030A:           ;******************************************************************************
030A:           ;
030A:           ; Print a file's contents to STDOUT:
030A:           ;
030A: C5        cat_file        push    bc
030B: D5                        push    de
030C: E5                        push    hl
030D: FDE5                      push    iy
030F: 213A03                    ld      hl, cat_file_prompt
0312: CD4B12                    call    puts
0315: 216DFB                    ld      hl, string_81_bfr
0318: 0651                      ld      b, 81
031A: CDBA11                    call    gets            ; Read the filename into buffer
031D: CD5B12                    call    stroup          ; Convert to upper case
0320: FD21BEFB                  ld      iy, fcb         ; Prepare fopen (only one FCB currently)
0324: 1161FB                    ld      de, string_12_bfr
0327: CD1C17                    call    fopen
032A: CD6114    cat_file_loop   call    fgetc           ; Get a single character
032D: 3805                      jr      c, cat_file_exit
032F: CD4012                    call    putc            ; Print character if not EOF
0332: 18F6                      jr      cat_file_loop   ; Next character
0334: FDE1      cat_file_exit   pop     iy
0336: E1                        pop     hl
0337: D1                        pop     de
0338: C1                        pop     bc
0339: C9                        ret
033A: 4341543A
033E: 2046494C
0342: 454E414D
0346: 453D00    cat_file_prompt defb    "CAT: FILENAME=", eos
0349:           ;
0349:           ;  directory - a simple wrapper for dirlist (necessary for printing the command
0349:           ; name)
0349:           ;
0349: E5        directory       push    hl
034A: 215503                    ld      hl, directory_msg
034D: CD4B12                    call    puts
0350: CD6F18                    call    dirlist
0353: E1                        pop     hl
0354: C9                        ret
0355: 44495245
0359: 43544F52
035D: 590D0A00  directory_msg   defb    "DIRECTORY", cr, lf, eos
0361:           ;
0361:           ; Disassemble a memory area
0361:           ;
0361: F5        disassemble     push    af  
0362: C5                        push    bc  
0363: D5                        push    de  
0364: E5                        push    hl  
0365: DDE5                      push    ix  
0367: 219D03                    ld      hl, dismsg1     ; Prompt for the start address
036A: CD4B12                    call    puts
036D: CDAF11                    call    get_word        ; Read user input
0370: E5                        push    hl              ; Save start address for later
0371: 21B103                    ld      hl, dismsg2     ; Prompt for end address
0374: CD4B12                    call    puts
0377: CDAF11                    call    get_word
037A: CD4C11                    call    crlf
037D: CD4C11                    call    crlf
0380: D1                        pop     de              ; Start address -> de
0381: E5                        push    hl              ; Push end address
0382: CDD403    disloop         call    disz80          ; Disassemble one instruction
0385: CD4C11                    call    crlf
0388: E1                        pop     hl  
0389: E5                        push    hl  
038A: A7                        and     a               ; Clear carry, just in case
038B: ED52                      sbc     hl, de          ; End address reached?
038D: 30F3                      jr      nc, disloop     ; No, continue disassembling
038F: 21B703                    ld      hl, dismsg3     ; Yes, print end message
0392: CD4B12                    call    puts
0395: E1                        pop     hl              ; Remove the end address copy
0396: DDE1                      pop     ix  
0398: E1                        pop     hl  
0399: D1                        pop     de  
039A: C1                        pop     bc  
039B: F1                        pop     af  
039C: C9                        ret
039D: 44495341
03A1: 5353454D
03A5: 424C453A
03A9: 20535441
03AD: 52543D00  dismsg1 defb    "DISASSEMBLE: START=", eos
03B1: 20454E44
03B5: 3D00      dismsg2 defb    " END=", eos
03B7: 0D0A454E
03BB: 44204F46
03BF: 20444953
03C3: 41535345
03C7: 4D424C45
03CB: 52205255
03CF: 4E2E0D0A
03D3: 00        dismsg3 defb    cr, lf, "END OF DISASSEMBLER RUN.", cr, lf, eos
;... ...John Kerr's Disassembler resides here... ...
081A:           #include        "../disassembler/dis_z80.asm"
081B:           ;
081B:           ;
081B:           ; Get and print disk info:
081B:           ;
081B: F5        disk_info       push    af
081C: E5                        push    hl
081D: 213F08                    ld      hl, disk_info_msg
0820: CD4B12                    call    puts
0823: CDBC12                    call    ide_get_id      ; Read the disk info into the IDE buffer
0826: 2113FE                    ld      hl, buffer + $13
0829: 3609                      ld      (hl), tab
082B: CD4B12                    call    puts            ; Print vendor information
082E: CD4C11                    call    crlf
0831: 212DFE                    ld      hl, buffer + $2d
0834: 3609                      ld      (hl), tab
0836: CD4B12                    call    puts
0839: CD4C11                    call    crlf
083C: E1                        pop     hl
083D: F1                        pop     af
083E: C9                        ret
083F: 494E464F
0843: 3A0D0A00  disk_info_msg   defb    "INFO:", cr, lf, eos
0847:           ;
0847:           ; Read data from disk to memory
0847:           ;
0847: F5        disk_transfer   push    af
0848: C5                        push    bc
0849: D5                        push    de
084A: E5                        push    hl
084B: DDE5                      push    ix
084D: 21C608                    ld      hl, disk_trx_msg_0
0850: CD4B12                    call    puts            ; Print Read/Write prompt
0853: CD5911    disk_trx_rwlp   call    getc
0856: CD4311                    call    to_upper
0859: FE52                      cp      'R'             ; Read?
085B: 2009                      jr      nz, disk_trx_nr ; No
085D: DD215613                  ld      ix, ide_rs      ; Yes, we will call ide_rs later
0861: 21D008                    ld      hl, disk_trx_msg_1r
0864: 180B                      jr      disk_trx_main   ; Prompt the user for parameters
0866: FE57      disk_trx_nr     cp      'W'             ; Write?
0868: 20E9                      jr      nz, disk_trx_rwlp
086A: DD21C413                  ld      ix, ide_ws      ; Yes, we will call ide_ws later
086E: 21EA08                    ld      hl, disk_trx_msg_1w
0871: CD4B12    disk_trx_main   call    puts            ; Print start address prompt
0874: CDAF11                    call    get_word        ; Get memory start address
0877: E5                        push    hl
0878: 210509                    ld      hl, disk_trx_msg_2
087B: CD4B12                    call    puts            ; Prompt for number of blocks
087E: CD8A11                    call    get_byte        ; There are only 128 block of memory!
0881: FE00                      cp      0               ; Did the user ask for 00 blocks?
0883: 2008                      jr      nz, disk_trx_1  ; No, continue prompting
0885: 213209                    ld      hl, disk_trx_msg_4
0888: CD4B12                    call    puts
088B: 1830                      jr      disk_trx_exit
088D: 212309    disk_trx_1      ld      hl, disk_trx_msg_3
0890: CD4B12                    call    puts            ; Prompt for disk start sector
0893: CDAF11                    call    get_word        ; This is a four byte address!
0896: 444D                      ld      bc, hl
0898: CDAF11                    call    get_word
089B: 545D                      ld      de, hl
089D: E1                        pop     hl              ; Restore memory start address
089E:                           ; Register contents:
089E:                           ;       A:  Number of blocks
089E:                           ;       BC: LBA3/2
089E:                           ;       DE: LBA1/0
089E:                           ;       HL: Memory start address
089E: F5        disk_trx_loop   push    af              ; Save number of sectors
089F: CDC408                    call    disk_trampoline ; Read/write one sector (F is changed!)
08A2: E5                        push    hl              ; Save memory address
08A3: C5                        push    bc              ; Save LBA3/2
08A4: 626B                      ld      hl, de          ; Increment DE (LBA1/0)
08A6: 010100                    ld      bc, $0001       ; by one and
08A9: 09                        add     hl, bc          ; generate a carry if necessary
08AA: 545D                      ld      de, hl          ; Save new LBA1/0
08AC: E1                        pop     hl              ; Restore LBA3/2 into HL (!)
08AD: 3001                      jr      nc, disk_trx_skip
08AF: 09                        add     hl, bc          ; Increment BC if there was a carry
08B0: 444D      disk_trx_skip   ld      bc, hl          ; Write new LBA3/2 into BC
08B2: E1                        pop     hl              ; Restore memory address
08B3: C5                        push    bc              ; Save LBA3/2
08B4: 010002                    ld      bc, $200        ; 512 byte per block
08B7: 09                        add     hl, bc          ; Set pointer to next memory block
08B8: C1                        pop     bc              ; Restore LBA3/2
08B9: F1                        pop     af
08BA: 3D                        dec     a               ; One block already done
08BB: 20E1                      jr      nz, disk_trx_loop
08BD: DDE1      disk_trx_exit   pop     ix
08BF: E1                        pop     hl
08C0: D1                        pop     de
08C1: C1                        pop     bc
08C2: F1                        pop     af
08C3: C9                        ret
08C4: DDE9      disk_trampoline jp      (ix)
08C6: 5452414E
08CA: 53464552
08CE: 2F00      disk_trx_msg_0  defb    "TRANSFER/", eos
08D0: 52454144
08D4: 3A200D0A
08D8: 20202020
08DC: 4D454D4F
08E0: 52592053
08E4: 54415254
08E8: 3D00      disk_trx_msg_1r defb    "READ: ", cr, lf, "    MEMORY START=", eos
08EA: 57524954
08EE: 453A200D
08F2: 0A202020
08F6: 204D454D
08FA: 4F525920
08FE: 53544152
0902: 543D00    disk_trx_msg_1w defb    "WRITE: ", cr, lf, "    MEMORY START=", eos
0905: 204E554D
0909: 42455220
090D: 4F462042
0911: 4C4F434B
0915: 53202835
0919: 31322042
091D: 59544529
0921: 3D00      disk_trx_msg_2  defb    " NUMBER OF BLOCKS (512 BYTE)=", eos
0923: 20535441
0927: 52542053
092B: 4543544F
092F: 523D00    disk_trx_msg_3  defb    " START SECTOR=", eos
0932: 204E6F74
0936: 68696E67
093A: 20746F20
093E: 646F2066
0942: 6F72207A
0946: 65726F20
094A: 626C6F63
094E: 6B732E0D
0952: 0A00      disk_trx_msg_4  defb    " Nothing to do for zero blocks.", cr, lf, eos
0954:           ;
0954:           ; Dump a memory area
0954:           ;
0954: F5        dump            push    af
0955: C5                        push    bc
0956: D5                        push    de
0957: E5                        push    hl
0958: 21B409                    ld      hl, dump_msg_1
095B: CD4B12                    call    puts            ; Print prompt
095E: CDAF11                    call    get_word        ; Read start address
0961: E5                        push    hl              ; Save start address
0962: 21C109                    ld      hl, dump_msg_2  ; Prompt for end address
0965: CD4B12                    call    puts
0968: CDAF11                    call    get_word        ; Get end address
096B: CD4C11                    call    crlf
096E: 23                        inc     hl              ; Increment stop address for comparison
096F: 545D                      ld      de, hl          ; DE now contains the stop address
0971: E1                        pop     hl              ; HL is the start address again
0972:                           ; This loop will dump 16 memory locations at once - even
0972:                           ; if this turns out to be more than requested.
0972: 0610      dump_line       ld      b, $10          ; This loop will process 16 bytes
0974: E5                        push    hl              ; Save HL again
0975: CD3312                    call    print_word      ; Print address
0978: 21C709                    ld      hl, dump_msg_3  ; and a colon
097B: CD4B12                    call    puts
097E: E1                        pop hl                  ; Restore address
097F: E5                        push    hl              ; We will need HL for the ASCII dump
0980: 7E        dump_loop       ld      a, (hl)         ; Get the memory content
0981: CD1212                    call    print_byte      ; and print it
0984: 3E20                      ld      a, ' '          ; Print a space
0986: CD4012                    call    putc
0989: 23                        inc     hl              ; Increment address counter
098A: 10F4                      djnz    dump_loop       ; Continue with this line
098C:                           ; This loop will dump the very same 16 memory locations - but
098C:                           ; this time printable ASCII characters will be written.
098C: 0610                      ld      b, $10          ; 16 characters at a time
098E: 3E20                      ld      a, ' '          ; We need some spaces
0990: CD4012                    call    putc            ; to print
0993: CD4012                    call    putc
0996: E1                        pop     hl              ; Restore the start address
0997: 7E        dump_ascii_loop ld      a, (hl)         ; Get byte
0998: CD0A11                    call    is_print        ; Is it printable?
099B: 3802                      jr      c, dump_al_1    ; Yes
099D: 3E2E                      ld      a, '.'          ; No - print a dot
099F: CD4012    dump_al_1       call    putc            ; Print the character
09A2: 23                        inc     hl              ; Increment address to read from
09A3: 10F2                      djnz    dump_ascii_loop
09A5:                           ; Now we are finished with printing one line of dump output.
09A5: CD4C11                    call    crlf            ; CR/LF for next line on terminal
09A8: E5                        push    hl              ; Save the current address for later
09A9: A7                        and     a               ; Clear carry
09AA: ED52                      sbc     hl, de          ; Have we reached the last address?
09AC: E1                        pop     hl              ; restore the address
09AD: 38C3                      jr      c, dump_line    ; Dump next line of 16 bytes
09AF: E1                        pop     hl
09B0: D1                        pop     de
09B1: C1                        pop     bc
09B2: F1                        pop     af
09B3: C9                        ret
09B4: 44554D50
09B8: 3A205354
09BC: 4152543D
09C0: 00        dump_msg_1      defb    "DUMP: START=", eos
09C1: 20454E44
09C5: 3D00      dump_msg_2      defb    " END=", eos
09C7: 3A2000    dump_msg_3      defb    ": ", eos
09CA:           ;
09CA:           ; Examine a memory location:
09CA:           ;
09CA: F5        examine         push    af
09CB: E5                        push    hl
09CC: 21F809                    ld      hl, examine_msg_1
09CF: CD4B12                    call    puts
09D2: CDAF11                    call    get_word        ; Wait for a four-nibble address
09D5: E5                        push    hl              ; Save address for later
09D6: 21160A                    ld      hl, examine_msg_2
09D9: CD4B12                    call    puts
09DC: E1        examine_loop    pop     hl              ; Restore address
09DD: 7E                        ld      a, (hl)         ; Get content of address
09DE: 23                        inc     hl              ; Prepare for next examination
09DF: E5                        push    hl              ; Save hl again for later use
09E0: CD1212                    call    print_byte      ; Print the byte
09E3: CD5911                    call    getc            ; Get a character
09E6: FE20                      cp      ' '             ; A blank?
09E8: 2007                      jr      nz, examine_exit; No - exit
09EA: 3E20                      ld      a, ' '          ; Print a blank character
09EC: CD4012                    call    putc
09EF: 18EB                      jr      examine_loop
09F1: E1        examine_exit    pop     hl              ; Get rid of save hl value
09F2: CD4C11                    call    crlf            ; Print CR/LF
09F5: E1                        pop     hl
09F6: F1                        pop     af
09F7: C9                        ret
09F8: 4558414D
09FC: 494E4520
0A00: 28747970
0A04: 65202720
0A08: 272F5245
0A0C: 54293A20
0A10: 41444452
0A14: 3D00      examine_msg_1   defb    "EXAMINE (type ' '/RET): ADDR=", eos
0A16: 20444154
0A1A: 413D00    examine_msg_2   defb    " DATA=", eos
0A1D:           ;
0A1D:           ; Fill a block of memory with a single byte - the user is prompted for the
0A1D:           ; start address, the length of the block and the fill value.
0A1D:           ;
0A1D: F5        fill            push    af              ; We will need nearly all registers
0A1E: C5                        push    bc
0A1F: D5                        push    de
0A20: E5                        push    hl
0A21: 21770A                    ld      hl, fill_msg_1  ; Prompt for start address
0A24: CD4B12                    call    puts
0A27: CDAF11                    call    get_word        ; Get the start address
0A2A: E5                        push    hl              ; Store the start address
0A2B: A7                        and     a               ; Clear carry
0A2C: 010080                    ld      bc, ram_start
0A2F: ED42                      sbc     hl, bc          ; Is the address in the RAM area?
0A31: 3009                      jr      nc, fill_get_length
0A33: 21950A                    ld      hl, fill_msg_4  ; No!
0A36: CD4B12                    call    puts            ; Print error message
0A39: E1                        pop     hl              ; Clean up the stack
0A3A: 1836                      jr      fill_exit       ; Leave routine
0A3C: 21840A    fill_get_length ld      hl, fill_msg_2  ; Prompt for length information
0A3F: CD4B12                    call    puts
0A42: CDAF11                    call    get_word        ; Get the length of the block
0A45:                           ; Now make sure that start + length is still in RAM:
0A45: 444D                      ld      bc, hl          ; BC contains the length
0A47: E1                        pop     hl              ; HL now contains the start address
0A48: E5                        push    hl              ; Save the start address again
0A49: C5                        push    bc              ; Save the length
0A4A: 09                        add     hl, bc          ; Start + length
0A4B: A7                        and     a               ; Clear carry
0A4C: 010080                    ld      bc, ram_start
0A4F: ED42                      sbc     hl, bc          ; Compare with ram_start
0A51: 300A                      jr      nc, fill_get_value
0A53: 21A90A                    ld      hl, fill_msg_5  ; Print error message
0A56: CD4B12                    call    puts
0A59: C1                        pop     bc              ; Clean up the stack
0A5A: E1                        pop     hl
0A5B: 1815                      jr      fill_exit       ; Leave the routine
0A5D: 218D0A    fill_get_value  ld      hl, fill_msg_3  ; Prompt for fill value
0A60: CD4B12                    call    puts
0A63: CD8A11                    call    get_byte        ; Get the fill value
0A66: C1                        pop     bc              ; Get the length from the stack
0A67: E1                        pop     hl              ; Get the start address again
...

This file has been truncated, please download it to see its full contents.

Code snippet #1

Plain text
Simple Z80-monitor - V 0.14a (B. Ulmann, September 2011 - June 2013)
   This monitor contains Brad Rodriguez' CAMEL Forth, 
                         John Kerr's Z80 disassembler
-------------------------------------------------------------------------------
Z> 
       

Code snippet #2

Plain text
Z> HELP: Known command groups and commands:

         C(ontrol group):
             C(old start), I(nfo), S(tart), W(arm start)
         D(isk group):
             I(nfo), M(ount), T(ransfer), U(nmount)
             R(ead), W(rite)
         F(ile group):
             C(at), D(irectory), L(oad), R(un)
         H(elp)
         M(emory group):
             (dis)A(ssemble), D(ump), E(xamine), F(ill), I(ntel Hex Load), 
             L(oad), R(egister dump), 
         S(ubsystem group):
             F(orth)
       

Code snippet #3

Plain text
Z> MEMORY/DISASSEMBLE: START=0000 END=0050

0000 F3          DI                
0001 31 3B FB    LD   SP,0FB3BH    
0004 18 17       JR   1DH          
0006 00          NOP               
0007 00          NOP               
0008 C5          PUSH BC           
0009 E5          PUSH HL           
000A DD E5       PUSH IX           
000C E1          POP  HL           
000D 29          ADD  HL,HL        
000E 01 4C 1D    LD   BC,1D4CH     
0011 09          ADD  HL,BC        
0012 4E          LD   C,(HL)       
0013 23          INC  HL           
0014 46          LD   B,(HL)       
0015 2B          DEC  HL           
0016 C5          PUSH BC           
0017 DD E1       POP  IX           
0019 E1          POP  HL           
001A C1          POP  BC           
001B DD E9       JP   (IX)         
001D 3E 80       LD   A,80H        
001F D3 03       OUT  (3),A        
0021 3E 0C       LD   A,0CH        
0023 D3 00       OUT  (0),A        
0025 AF          XOR  A            
0026 D3 01       OUT  (1),A        
0028 3E 03       LD   A,3          
002A D3 03       OUT  (3),A        
002C 3E 07       LD   A,7          
002E D3 02       OUT  (2),A        
0030 21 5A 01    LD   HL,15AH      
0033 CD 4B 12    CALL 124BH        
0036 3A 3C FB    LD   A,(0FB3CH)   
0039 FE AA       CP   0AAH         
003B 28 18       JR   Z,55H        
003D 21 DA 02    LD   HL,2DAH      
0040 CD 4B 12    CALL 124BH        
0043 21 00 80    LD   HL,8000H     
0046 54          LD   D,H          
0047 5D          LD   E,L          
0048 13          INC  DE           
0049 01 FF 7F    LD   BC,7FFFH     
004C 36 00       LD   (HL),0       
004E ED B0       LDIR              
0050 21 3C FB    LD   HL,0FB3CH    

END OF DISASSEMBLER RUN.

Z> 
       

Credits

Bernd Ulmann

Bernd Ulmann

9 projects • 9 followers
I love all things that can compute, especially analog computers.

Comments