Files
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

240 lines
5.5 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

title 'CP/M-86 Loader'
; The CPMLDR consists of this module along with the
; LDRBDOS and LBIOS.
; CPMLDR resides on the first two tracks of a
; CP/M-86 system diskette and is brought into memory
; by the ROM bootstrap loader to load initiate CP/M-86
; It opens the file 'CPM.SYS' using the LDRBDOS and LBIOS
; and then reads it into memory. Finally, a jump to the BIOS
; initialization entry point starts CP/M-86
; The first 128 byte record of the CPM.SYS file is a header
; with the following format:
; ty rb 1 ;seg type (not used here)
; len rw 1 ;length (not used here)
; abs dw ldrstart ;absolute segment address for LOADER
; min rw 1 ;minimum mem (not used here)
; max rw 1 ;max mem needed (not used here)
; (This header record is constructed automatically by the
; GENCMD utility).
; CPMLDR may be read into any segment that does not
; overlap the desired system load segment as it makes
; all memory references using copies of the CS: register
; it is entered with.
false equ 0
true equ not false
cr equ 0dh
lf equ 0ah
lbios_offset equ 1200h ; offset of LBIOS
biosoff equ 2500h ; offset of BIOS from start of CPM.SYS
; this is the entry point into CPM.SYS
bootdrv equ 0 ; boot drive always zero
; 128 bytes of CPM.SYS
lbdosoff equ 406H ;location of LBDOS in LOADER
bdos_int equ 224 ;lbdos interrupt number
; dummy section for interrupt vectors
dseg 0
org 0
abs_zero rw 2*bdosint
bdos_offset rw 1
bdos_segment rw 1
; bdos function numbers
coutf equ 2
pstrf equ 9
seldsk equ 14
openf equ 15
readsf equ 20
dmaf equ 26
dmabf equ 51
;*******************************
;*
;* CPMLDR starts here
;*
;*******************************
cseg
org 0 ; JMPF to here from boot ROM
jmp LBIOS ; allow loader BIOS to
; initialize
start: ; loader BIOS jumps here
xor ax,ax ! mov ds,ax ; temp DS at absolute zero
mov bdos_offset,lbdosoff ; to patch in interrupt table
mov bdos_segment,cs ; offset and segment
mov ax,cs ! mov ss,ax ; make ss, ds, es = cs
mov ds,ax ! mov es,ax
mov sp,offset(stack) ; set up local stack
call initlbdos ;warm up lbdos and lbios
call openfnc ;open CPM.SYS
cmp al,255 ! jne perr ; insure good file
mov dx,offset nofile ! call msg ; no CPM.SYS file
jmp stop ; then halt the machine
perr:
mov dx,cs ! call setdmab
mov dx,offset page1 ! call setdma ;read first page of CPM.SYS
call read
mov ax,word ptr page1+3 ;get abs field from header
mov ldseg,ax ; save it and
mov dx,ax ! call setdmab ; set DMA segment for disk IO
mov dx,offset segment ! call msg ; put memory map on console
mov ax,ldseg ! call phex ; print base system segment
;
mov dx,0 ;offset of CPM in segment
readit:
call setdma ; set DMA offset for
push dx ! call read ; next sector read
cmp al,01H ! je done ; check for EOF
cmp al,0 ! je prerr ; check for good write
mov dx,offset rerr ! call msg ; print READ ERROR message
jmp stop ; hard stop on any error
prerr: pop dx ! add dx,80h ; address for next record
jmp readit
done:
mov dx,offset lenmsg ! call msg ; print length message
pop ax ! dec ax ! call phex ; print last address
call pcrlf ; and a crlf
jmpf bios ; leap to BIOS initialization
;*****************************
;*
;* subroutines
;*
;*****************************
;******
phex: ;print 4 hex characters from ax
mov cx,0404h ; 4 in both CH and CL
lhex:
rol ax,cl ; rotate left 4
push cx ! push ax ; save crucial registers
call pnib ; print hex nibble
pop ax ! pop cx ; restore registers
dec ch ! jnz lhex ; and loop four times
ret
pnib: ;print low nibble in AL as hex char
and al,0fh ! cmp al,9
ja p10 ;above 9 ?
add al,'0' ;digit
jmp prn
p10: add al,'A'-10 ;char a-e
prn: mov dl,al
;******
putchar:
mov cl,coutf
jmp sys_vec
;******
initlbdos:
mov cl,seldsk ! mov dx,bootdrv ; select boot disk
jmp sys_vec
;******
openfnc:
mov cl,openf ! mov dx,offset fcb ; fcb already initialized
mov cl,openf
jmp sys_vec
;********
;
setdma: ;set new dma addr in dx
mov cl,dmaf
jmp sys_vec
;********
;
setdmab: ; set new dma segment base from DX
mov cl,dmabf
jmp sys_vec
;******
;
pcrlf: mov dx,offset crlf ;print carriage return, line feed
;******
;
msg: ;print msg starting at dx until $
mov cl,pstrf ;print string function
jmp sys_vec
;*****
;
read:
mov dx,offset fcb ! mov cl,readsf
; jmp sys_vec
;******
;
sys_vec:
int bdos_int
ret
;******
;
stop: hlt ; hard stop 8086 for error
jmp stop
;********************************
;*
;* DATA AREA
;*
;********************************
nofile db cr,lf,'The File CPM.SYS Not Found On This Disk$'
rerr db cr,lf,'Error In Reading CPM.SYS$'
segment db cr,lf,'Segment Address = $'
lenmsg db cr,lf,' Last Offset = $'
crlf db cr,lf,'$'
; vector for jmpf indirect to start CP/M
bios dd abs_zero ; (dummy value)
org offset bios ; overlay preceding with DW's
biosstart dw biosoff ; first word is BIOS offset
ldseg rw 1 ; second is segment to put CPM.SYS
fcb db 0,'CPM ','SYS',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
org (offset $+1) and 0FFFEh ; even address for stack
rw 32
stack equ offset $
dseg
org stack
page1 rb 128
; dummy section for BIOS init label
org lbios_offset
lbios:
end