Assembly Disc Access Primer, a TatungBytes course: DISKMON reading the hidden sector IDs of the course's own practice disc, on a rainbow sunburst
← Back to Modules
module
5

Calling the BDOS

Introduction

So far DISKMON has only talked to the MOS. Everything in Part two goes through the BDOS instead, and every one of those calls has the same shape. This section makes the first one - the simplest there is, printing - and then looks at where the BDOS is, because that decides how much memory DISKMON has.

Making a Call

A BDOS call is three things:

  1. The function number in C. Each thing the BDOS can do has a number: 9 prints a string, 2 prints a character, and from S7 on you will meet 15 (open a file), 20 (read from it), and others.
  2. Whatever that function needs, in the registers it names. Function 9 wants the address of the string in DE; the string ends with a $, which is not printed. Function 2 wants the character in E.
  3. CALL 5.

Address 0005h is not the BDOS itself. It holds a jump to it - three bytes, C3 00 EC: JP EC00H. So the BDOS starts at EC00h, and DISKMON can find out where by reading the two bytes at 0006h.

The Code

New since S4: the nine lines from LD DE,BDOSMSG to the second CALL NEWLINE, and BDOSMSG at the end.

; DISKMON - reads and writes the Einstein's discs.
; The Assembly Disc Access Primer's program, as it stands at the end of
; the section named in this file's name.

        ORG 0100H

START:  LD HL,TITLE
        CALL PRINT
        LD HL,MEMMSG
        CALL PRINT
        LD HL,0100H
        LD B,8
        CALL SHOWMEM
        CALL NEWLINE
        LD DE,BDOSMSG
        LD C,9
        CALL 5
        LD HL,(0006H)
        LD A,H
        CALL PHEX
        LD A,L
        CALL PHEX
        CALL NEWLINE
        RET

; --------------------------------------------------------------- output
; PRINT: print the zero-terminated text at HL.
PRINT:  LD A,(HL)
        OR A
        RET Z
        CALL PUTC
        INC HL
        JR PRINT

; PUTC: print the character in A, keeping BC, DE and HL.
PUTC:   PUSH BC
        PUSH DE
        PUSH HL
        RST 8
        DEFB 158
        POP HL
        POP DE
        POP BC
        RET

; NEWLINE: carriage return, then line feed.
NEWLINE: LD A,13
        CALL PUTC
        LD A,10
        JP PUTC

; PHEX: print A as two hex digits.
PHEX:   PUSH AF
        RRCA
        RRCA
        RRCA
        RRCA
        CALL DIGIT
        POP AF
DIGIT:  AND 0FH
        ADD A,'0'
        CP '9'+1
        JR C,DIG1
        ADD A,7
DIG1:   JP PUTC

; SHOWMEM: print B bytes from HL in hex, each followed by a space.
SHOWMEM: LD A,(HL)
        CALL PHEX
        LD A,' '
        CALL PUTC
        INC HL
        DJNZ SHOWMEM
        RET

; ----------------------------------------------------------------- data
TITLE:  DEFB 'DISKMON',13,10,0
MEMMSG: DEFB 'AT 0100: ',0
BDOSMSG: DEFB 'BDOS AT $'

LD HL,(0006H) loads the address part of the jump - low byte from 0006h, high byte from 0007h - and DISKMON prints H then L, the way you read an address.

Run it

Assemble, replace DISKMON.COM on diskmon.dsk, start MAME as in S2, and type 1:DISKMON.

What you should see

0:1:DISKMON
DISKMON
AT 0100: 21 6D 01 CD 2E 01 21 77
BDOS AT EC00

0:

DISKMON finds the BDOS at EC00h

The first eight bytes have changed since S4 - TITLE and PRINT have moved further along now that START is longer - but BDOS AT came from the BDOS, not from PRINT.

Where Everything Is

Here is memory while DISKMON runs under XtalDOS:

Address What is there
0000h JP FA03H - the DOS's restart (a "warm boot")
0005h JP EC00H - the way into the BDOS
0100h Your program. XtalDOS loads it here and calls it
up to E0FFh Free for your program
E100h-EBFFh The CCP, the part of XtalDOS that shows 0: and reads your commands. Your program's stack and the address RET returns to are in here too
EC00h The BDOS

That middle row is the one to think about. XtalDOS starts your program with a CALL from inside the CCP, so DISKMON's own RET goes back into it, and the stack it starts with is there as well. If DISKMON writes over E100h-EBFFh and then ends with RET, it returns into whatever it wrote there.

There is another way to finish: JP 0. That jumps to the warm boot, which puts the CCP back before showing 0:. A program that ends with JP 0 may use the CCP's memory as its own.

So: below E100h is DISKMON's. End with RET and leave E100h-EBFFh alone; or end with JP 0 and you may use it too. EC00h and above is the BDOS, which DISKMON needs every time it calls 5.

Change One Thing

  • Change LD C,9 to LD C,2. DE still holds BDOSMSG's address. Which register does function 2 print from, and what will appear in place of BDOS AT? (Look up BDOSMSG's address in the -l listing.)
  • Change the final RET to JP 0. What will be different on the screen, and what will be different in the machine?
  • Take the $ off the end of BDOSMSG. What will function 9 print?

Summary

DISKMON calls the BDOS: function number in C, its other inputs where it wants them, CALL 5. The BDOS is at EC00h; the CCP sits just below it, holding DISKMON's return address; everything below E100h is DISKMON's.

Next

S6 builds the 36 bytes the BDOS needs to know which file you mean: the File Control Block.

Get the Newsletter

New guides, disk images and community finds, roughly once a quarter. No spam, we promise, this isn't Tatung's marketing department.
Your subscription could not be saved. Please try again.
Your subscription has been successful.

Newsletter

Subscribe to our newsletter and stay updated.

This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.