Files
Digital-Research-Source-Code/CPM OPERATING SYSTEMS/CPM 86/CALPC/CALUTILS/LOADCPM.ASM
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

237 lines
6.8 KiB
NASM
Raw 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.

;---------------------------------------------------------------------
; LOADCPM.ASM (FOR CAL-PC MSDOS 2.11 - ASSEMBLE USING A86.COM)
; 28-10-88
; STEPHEN HUNT
;---------------------------------------------------------------------
; 28-12-89
; Modified to attempt to open the CPM.SYS file in the root directory
; if it could not be found in the current directory
;---------------------------------------------------------------------
;
cr equ 0dh ; carriage return
lf equ 0ah ; line feed
eof equ 01ah ; end of file marker
;
dos equ 21h
;
;---------------------------------------------------------------------
; jump to start of code
;---------------------------------------------------------------------
;
loadcpm:
;
jmp start
;
db 'LOADCPM version 1.1 Copyright (C) Stephen Hunt'
db eof
;
;---------------------------------------------------------------------
; tell 'em what were up to
;---------------------------------------------------------------------
;
start:
;
mov dx,offset loading
call print_string
;
;---------------------------------------------------------------------
; open the CPM.SYS file
;---------------------------------------------------------------------
;
mov dx,offset cpm_sys+1 ; assume 'CPM.SYS'
call open_cpm ; open file
jnc read_cpm_sys ; ok - continue
;
mov dx,offset cpm_sys ; assume '\CPM.SYS'
call open_cpm ; open file
jnc read_cpm_sys ; ok - continue
;
mov dx,offset err_open ; 'cannot find CPM.SYS'
jmp error_exit ; exit with error
;---------------------------------------------------------------------
; read the CPM.SYS file (upto 32k bytes, usually only 16k bytes)
;---------------------------------------------------------------------
;
read_cpm_sys:
;
mov bx,word ptr cpm_hnd
mov dx,offset cpm_buf
mov cx,32768
mov ah,03fh
int dos ; read 32768 bytes of CPM.SYS
;
mov word ptr cpm_siz,ax ; store number of bytes read
;
pushf ; save read error status
call closecpm ; close CPM.SYS file
popf ; restore read error status
;
jnc check_header ; continue if read successful
;
mov dx,offset err_read ; 'error reading CPM.SYS'
jmp error_exit ; exit with error
;---------------------------------------------------------------------
; check that the CPM.SYS header record is valid
;---------------------------------------------------------------------
;
check_header:
;
cmp word ptr cpm_siz,0 ; q. was anything read ?
jz check_header_err ; no - error
;
mov si,offset cpm_buf
cmp byte ptr 0[si],1 ; q. code segment group type present ?
jnz check_header_err ; no - error
;
mov ax,word ptr 1[si] ; get group length in paragraphs
mov dx,010h
mul dx ; convert to length in bytes
mov word ptr cpm_len,ax ; and store it
;
mov bx,word ptr cpm_siz
cmp bx,ax ; q. file size greater than code length ?
jb check_header_err ; no - error
;
sub bx,080h ; subtract length of header record
sub bx,ax ; then the code length
cmp bx,080h ; q. (file size less header) more than
; ; 128 bytes larger than code length ?
jae check_header_err ; yes - error
;
cmp word ptr 3[si],0 ; q. base segment defined ?
jz check_header_err ; no - error
;
mov ax,word ptr 1[si]
cmp ax,word ptr 5[si] ; q. code length equal minimum length ?
jnz check_header_err ; no - error
;
cmp word ptr 7[si],0 ; q. maximum length defined ?
jnz check_header_err ; yes - error
;
add si,9 ; point to next group descriptor
mov cx,128 -9
cld
;
check_header_loop:
;
cmp byte ptr 0[si],0 ; q. any more descriptors defined ?
jnz check_header_err ; yes - error
loop check_header_loop ; loop until finished
;
jmp reset_int3 ; reset int 3 vector
;
check_header_err:
;
mov dx,offset err_head ; 'invalid CPM.SYS header'
jmp error_exit ; exit with error
;---------------------------------------------------------------------
; reset interrupt 3 to use the prom interrupt 3 routine (FC00:32BE).
;---------------------------------------------------------------------
;
reset_int3:
;
push ds
mov dx,0fc00h ; segment FC00h
mov ds,dx
mov dx,032beh ; offset 32BEh
mov al,3
mov ah,025h
int dos ; reset int 3
pop ds
;---------------------------------------------------------------------
; relocate cpm image, set segment registers and jump to it.
;---------------------------------------------------------------------
;
move_cpm:
;
mov ax,word ptr cpm_buf +3
mov es,ax ; es points to cpm segment
;
mov si,offset cpm_buf +080h
xor di,di ; set source + destination pointers
;
mov cx,word ptr cpm_len ; set length of code to move
;
cld ; clear the direction flag
cli ; plus the interrupt flag
;
rep movsb ; move it !!!!
;
mov ds,ax
push ax ; push cpm segment address on stack
mov ax,02500h
push ax ; push bios cold boot address on stack
;
retf ; return far to CPM-86 !!!
;---------------------------------------------------------------------
; Subroutines
;---------------------------------------------------------------------
; Open CPM.SYS file
;---------------------------------------------------------------------
;
open_cpm:
;
xor al,al
mov ah,03dh
int dos ; open CPM.SYS file
mov word ptr cpm_hnd,ax ; save file handle
;
ret
;---------------------------------------------------------------------
; Close CPM.SYS file
;---------------------------------------------------------------------
;
close_cpm:
;
mov bx,word ptr cpm_hnd
mov ah,03eh
int dos ; close CPM.SYS file
;
ret
;---------------------------------------------------------------------
; print string at offset dx
;---------------------------------------------------------------------
;
print_string:
;
mov ah,09h
int dos ; print string
;
ret
;---------------------------------------------------------------------
; print string and exit
;---------------------------------------------------------------------
;
error_exit:
;
call print_string
mov ah,04ch
xor al,al
int dos ; return to dos
;
;---------------------------------------------------------------------
; data
;---------------------------------------------------------------------
;
loading db cr,lf,'Loading CP/M-86 $'
;
err_open db cr,lf,lf,'Unable to open CPM.SYS',cr,lf,'$'
err_read db cr,lf,lf,'Error reading CPM.SYS',cr,lf,'$'
err_head db cr,lf,lf,'Invalid CPM.SYS header',cr,lf,'$'
;
cpm_sys db '\CPM.SYS',0 ; asciiz file name
cpm_hnd dw 0 ; file handle
cpm_siz dw 0 ; file size
cpm_len dw 0 ; code length
;
cpm_buf db 32768 dup (0) ; cpm.sys load buffer
;
db 0 ; spare
;
;---------------------------------------------------------------------
;
;---------------------------------------------------------------------
;
end