mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-28 10:54:18 +00:00
Upload
Digital Research
This commit is contained in:
252
CONTRIBUTIONS/cpm-handbook/cpmsrc/FIG7-5.ASM
Normal file
252
CONTRIBUTIONS/cpm-handbook/cpmsrc/FIG7-5.ASM
Normal file
@@ -0,0 +1,252 @@
|
||||
; Figure 7-5.
|
||||
;
|
||||
; Example Put CP/M
|
||||
;
|
||||
; This program writes out the CP/M Cold Boot Loader, the
|
||||
; CCP, BDOS and BIOS to a floppy diskette. It runs under
|
||||
; CP/M as a normal Transient Program.
|
||||
;
|
||||
Version EQU '01' ;Equates used in the sign on message
|
||||
Month EQU '07'
|
||||
Day EQU '24'
|
||||
Year EQU '82'
|
||||
;
|
||||
;
|
||||
; The actual PUTCPMF5.COM program consists of this code,
|
||||
; plus the BOOTF5.HEX, the CCP, BDOS and BIOS.
|
||||
;
|
||||
; When this program executes, the memory image should
|
||||
; look like this :
|
||||
;
|
||||
; Component Base Address
|
||||
; BIOS 1F80H
|
||||
; BDOS 1180H
|
||||
; CCP 0980H
|
||||
; BOOTF5 0780H
|
||||
;
|
||||
; The components are produced as follows :
|
||||
;
|
||||
; BIOS.HEX By assembling source code
|
||||
; BDOS ) From a CPMnn.COM file output
|
||||
; CCP ) by MOVCPM and SAVEd on disk
|
||||
; BOOTF5.HEX By assembling source code
|
||||
;
|
||||
; The components are pieced together using DDT with the
|
||||
; following commands :
|
||||
;
|
||||
; DDT CPMnn.COM
|
||||
; IPUTCPMF5.HEX
|
||||
; R (Reads in this program)
|
||||
; IBOOTF5.HEX
|
||||
; R680 (Reads in Boot at 0780H)
|
||||
; IBIOS.HEX
|
||||
; R2980 (Reads in BIOS at 1F80H)
|
||||
; G0 (Exit from DDT)
|
||||
; SAVE 40 PUTCPMF5.COM (Create final .COM file)
|
||||
;
|
||||
; The actual layout of the diskette is as follows :
|
||||
;
|
||||
; Track 0 Sector
|
||||
; 1 2 3 4 5 6 7 8 9
|
||||
; Head +-----+-----+-----+-----+-----+-----+-----+-----+-----+
|
||||
; 0 |Boot |<======== CCP ========>|<======= BDOS ========|
|
||||
; +-----+-----+-----+-----+-----+-----+-----+-----+-----+
|
||||
; 1 |====== BDOS ====>|<============= BIOS ============>|
|
||||
; +-----+-----+-----+-----+-----+-----+-----+-----+-----+
|
||||
; 10 11 12 13 14 15 16 17 18
|
||||
; Sector
|
||||
;
|
||||
; Equates for defining memory size and the base address and
|
||||
; length of the system components.
|
||||
;
|
||||
Memory$Size EQU 64 ;Number of Kbytes of RAM
|
||||
;
|
||||
; The BIOS Length must match that declared in the BIOS.
|
||||
;
|
||||
BIOS$Length EQU 0900H
|
||||
;
|
||||
Boot$Length EQU 512
|
||||
CCP$Length EQU 0800H ;Constant
|
||||
BDOS$Length EQU 0E00H ;Constant
|
||||
;
|
||||
Length$In$Bytes EQU CCP$Length + BDOS$Length + BIOS$Length
|
||||
;
|
||||
Start$Image EQU 980H - Boot$Length ;Address of CP/M Image
|
||||
Length$Image EQU Length$In$Bytes + Boot$Length
|
||||
;
|
||||
;
|
||||
; Disk Characteristics
|
||||
;
|
||||
; These equates describe the physical characteristics of
|
||||
; the floppy diskette so that the program can move from
|
||||
; one sector to the next, updating the track and resetting
|
||||
; the sector when necessary.
|
||||
;
|
||||
First$Sector$on$Track EQU 1
|
||||
Last$Sector$on$Track EQU 18
|
||||
Last$Sector$on$Head$0 EQU 9
|
||||
Sector$Size EQU 512
|
||||
;
|
||||
;
|
||||
; Controller Characteristics
|
||||
;
|
||||
; On this computer system, the floppy disk controller can write
|
||||
; multiple sectors in a single command. However, in order to
|
||||
; to produce a more general example it is shown only reading one
|
||||
; sector at a time.
|
||||
;
|
||||
Sectors$Per$Write EQU 1
|
||||
;
|
||||
;
|
||||
; Cold Boot Characteristics
|
||||
;
|
||||
Start$Track EQU 0 ;Initial values for CP/M image
|
||||
Start$Sector EQU 1 ;= " =
|
||||
Sectors$To$Write EQU (Length$Image + Sector$Size - 1) / Sector$Size
|
||||
;
|
||||
|
||||
;
|
||||
B$PRINTS EQU 9 ;Print string terminated by $
|
||||
BDOS EQU 5 ;BDOS Entry Point
|
||||
;
|
||||
;
|
||||
|
||||
ORG 100H
|
||||
Put$CPM:
|
||||
JMP Main$Code ;Enter main code body
|
||||
;For reasons of clarity, the main
|
||||
; data structures are shown before the
|
||||
; executable code.
|
||||
CR EQU 0DH ;Carriage Return
|
||||
LF EQU 0AH ;Line Feed
|
||||
;
|
||||
Signon$Message:
|
||||
DB CR,LF,'Put CP/M on Diskette'
|
||||
DB CR,LF
|
||||
DB 'Version '
|
||||
DW Version
|
||||
DB ' '
|
||||
DW Month
|
||||
DB '/'
|
||||
DW Day
|
||||
DB '/'
|
||||
DW Year
|
||||
DB CR,LF,'$'
|
||||
|
||||
;
|
||||
; Disk Control Tables
|
||||
;
|
||||
Disk$Control$5 EQU 45H ;5 1/4" Control Byte
|
||||
Command$Block$5 EQU 46H ;Control Table Pointer
|
||||
Disk$Status EQU 43H ;Completion status
|
||||
;
|
||||
;
|
||||
; The command table Track and DMA$Address can also be used
|
||||
; as working storage and updated as the load process
|
||||
; continues. The Sector in the command table cannot be
|
||||
; used directly as the disk controller requires it to be
|
||||
; the sector number on the specified head (1 - 9) rather
|
||||
; than the sector number on track. Hence a separate variable
|
||||
; must be used.
|
||||
;
|
||||
Sector: DB Start$Sector
|
||||
;
|
||||
Command$Table: DB 02H ;Command - Write
|
||||
Unit: DB 0 ;Unit (Drive) number = 0 or 1
|
||||
Head: DB 0 ;Head number = 0 or 1
|
||||
Track: DB Start$Track ;Used as working variable
|
||||
Sector$on$head: DB 0 ;Converted by low-level driver
|
||||
Byte$Count: DW Sector$Size * Sectors$Per$Write
|
||||
DMA$Address: DW Start$Image
|
||||
Next$Status: DW Disk$Status ;Pointer to next Status Block
|
||||
; if commands are chained.
|
||||
Next$Control: DW Disk$Control$5 ;Pointer to next Control Byte
|
||||
; if commands are chained.
|
||||
|
||||
Main$Code:
|
||||
LXI SP,Put$CPM ;Stack grows down below code
|
||||
|
||||
LXI D,Signon$Message ;Sign on
|
||||
MVI C,B$PRINTS ;Print string until $
|
||||
CALL BDOS
|
||||
|
||||
LXI H,Command$Table ;Point the disk controller at
|
||||
SHLD Command$Block$5 ; the command block
|
||||
|
||||
MVI C,Sectors$To$Write ;Set sector count
|
||||
Write$Loop:
|
||||
CALL Put$CPM$Write ;Write data onto diskette
|
||||
DCR C ;Downdate sector count
|
||||
JZ 0 ;Warm Boot
|
||||
|
||||
LXI H,Sector ;Update sector number
|
||||
MVI A,Sectors$Per$Write ; by adding on number of sectors
|
||||
ADD M ; by controller
|
||||
MOV M,A ;Save result
|
||||
MVI A,Last$Sector$On$Track + 1 ;Check if at end of track
|
||||
CMP M
|
||||
JNZ Not$End$Track
|
||||
|
||||
MVI M,First$Sector$On$Track ;Yes, reset to beginning
|
||||
LHLD Track ;Update Track number
|
||||
INX H
|
||||
SHLD Track
|
||||
|
||||
Not$End$Track:
|
||||
LHLD DMA$Address ;Update DMA Address
|
||||
LXI D,Sector$Size * Sectors$Per$Write
|
||||
DAD D
|
||||
SHLD DMA$Address
|
||||
JMP Write$Loop ;Write next block
|
||||
;
|
||||
Put$CPM$Write: ;At this point, the description of the
|
||||
; operation required is in the variables
|
||||
; contained in the Command Table, along
|
||||
; with the Sector variable.
|
||||
|
||||
PUSH B ;Save sector count in C
|
||||
|
||||
;------ Change this routine to match the disk controller in use ------
|
||||
|
||||
MVI B,0 ;Assume head 0
|
||||
LDA Sector ;Get requested sector
|
||||
MOV C,A ;Take a copy of it
|
||||
CPI Last$Sector$on$Head$0+1 ;Check if on head 1
|
||||
JC Head$0 ;No
|
||||
SUI Last$Sector$on$Head$0 ;Bias down for head 1
|
||||
MOV C,A ;Save copy
|
||||
INR B ;Set head 1
|
||||
Head$0:
|
||||
MOV A,B ;Get head
|
||||
STA Head
|
||||
MOV A,C ;Get sector
|
||||
STA Sector$On$Head
|
||||
|
||||
LXI H,Disk$Control$5 ;Activate controller
|
||||
MVI M,80H
|
||||
|
||||
Wait$For$Boot$Complete:
|
||||
MOV A,M ;Get status byte
|
||||
ORA A ;Check if complete
|
||||
JNZ Wait$For$Boot$Complete ;No
|
||||
;Yes, check for errors
|
||||
LDA Disk$Status
|
||||
CPI 80H
|
||||
JC Put$CPM$Error ;Yes, an error occurred
|
||||
|
||||
;------ End of Physical Write routine ------
|
||||
|
||||
POP B ;Recover sector count in C
|
||||
RET
|
||||
;
|
||||
Put$CPM$Error:
|
||||
LXI D,Put$CPM$Error$Message
|
||||
MVI C,B$PRINTS ;Print string until $
|
||||
CALL BDOS ;Output error message
|
||||
JMP Main$Code ;Restart the loader
|
||||
;
|
||||
|
||||
Put$CPM$Error$Message:
|
||||
DB CR,LF,'Error in writing CP/M - retrying...',CR,LF,'$'
|
||||
END Put$CPM
|
||||
|
||||
Reference in New Issue
Block a user