Files
Digital-Research-Source-Code/MPM OPERATING SYSTEMS/MPM I/MPM I SOURCE/06/genmod.asm
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

1 line
11 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.

TITLE 'GENMOD - MP/M RELOCATABLE MODULE GENERATOR 1/80'
; RELOCATING LOADER PROGRAM WITH MODULE GENERATION
;
; COPYRIGHT (C) 1979, 1980
; DIGITAL RESEARCH
; BOX 579, PACIFIC GROVE
; CALIFORNIA, 93950
;
;
; Revised:
; 19 Jan 80 by Thomas Rolander
ORG 000H ;BASE OF RELOCATABLE SEGMENT
BASE EQU $
ORG 100H ;BASE OF MP/M PROGRAM AREA
JMP START
DB ' COPYRIGHT (C) 1980, DIGITAL RESEARCH '
;
STKSIZ EQU 64 ;32 LEVEL WORKING STACK
;
; MISCELLANEOUS ADDRESS CONSTANTS
BOOT EQU BASE+0 ;SYSTEM REBOOT
BDOS EQU BASE+5 ;DOS ENTRY POINT
TOP EQU BASE+6 ;CONTAINS TOP OF MEMORY
DFCB EQU BASE+5CH ;DEFAULT FILE CONTROL BLOCK
DBF EQU BASE+80H ;DEFAULT BUFFER
RWORK EQU BASE+700H ;BASE OF RELOCATION WORK AREA
RMOD EQU BASE+600H ;MODULE RELOCATOR BASE
RSIZE EQU RMOD+1 ;MODULE SIZE FIELD
DSIZE EQU RMOD+4 ;DATA SIZE FIELD
;
; BDOS ENTRY FUNCTIONS
CONOF EQU 2 ;CONSOLE OUTPUT
OPF EQU 15 ;FILE OPEN FUNCTION
CLF EQU 16 ;FILE CLOSE FUNCTION
DLF EQU 19 ;FILE DELETE FUNCTION
RDF EQU 20 ;READ DISK
WRF EQU 21 ;WRITE DISK
MKF EQU 22 ;MAKE FILE
PRF EQU 9 ;PRINT BUFFER
DMF EQU 26 ;SET DMA ADDRESS
;
; NON GRAPHIC CHARACTERS
CR EQU 0DH ;CARRIAGE RETURN
LF EQU 0AH ;LINE FEED
DEOF EQU 1AH ;END OF FILE
;
START:
LXI SP,STACK
;
CALL SETUP ;SET UP FILES
XRA A ;ZERO IN ACCUM
STA PASS ;PASS = 0
LXI H,0
SHLD HLOC ;HLOC = 0
CALL HREAD
LHLD HLOC ;HIGH ADDRESS TO H,L
INX H ;+1
PUSH H
; CLEAR THE RELOCATION BIT MAP
CALL FINDBYTE ;HLOC+1 IS TRANSLATED TO AN ABS ADDR
; MOVE H,L TO NEXT PARAGRAPH BOUNDARY
ADJ0: MOV A,L
ANI 7FH
JZ ADJ1
INX H ;TO NEXT ADDRESS
JMP ADJ0
ADJ1: DCX H
SHLD LBYTE ;LAST BYTE TO WRITE
XCHG ;LAST BYTE TO ZERO IS IN D,E
POP H ;RECALL HLOC+1
; CLEAR ALL BYTES FROM H,L THROUGH D,E
CLER0: MOV A,E
SUB L
MOV A,D
SBB H
JC CLER1
MVI M,0 ;CLEAR ANOTHER BYTE
INX H
JMP CLER0
CLER1: ;BIT VECTOR CLEARED
; THE RELOCATION BIT VECTOR IS BUILT DURING THE SECOND PASS
LXI H,PASS
INR M ;PASS = 1
CALL HREAD
; BIT VECTOR BUILT, WRITE THE MODULE
CALL TERMINATE
LXI D,OKMSG ;OPERATION COMPLETE
CALL PRINT
JMP FINIS
OKMSG: DB CR,LF,'MODULE CONSTRUCTED$'
;
; UTILITY SUBROUTINES
;
HREAD: ;HEX FORMAT READ SUBROUTINE
; INPUT RECORDS TAKE THE FORM:
; :NNLLLLTTD1D2D3...DNCC
; WHERE -
; NN IS THE RECORD LENGTH (00-FF)
; LLLL IS THE LOAD ADDRESS (0000-FFFF)
; TT IS THE RECORD TYPE (ALWAYS 00)
; D1-DN ARE THE DATA BYTES
; CC IS THE CHECKSUM
; THE LAST RECORD HAS A LENGTH OF ZERO, AND LLLL IS THE
; STARTING ADDRESS FOR THE MODULE (IGNORED HERE)
;
CALL DISKR ;NEXT INPUT CHARACTER TO ACCUM
CPI DEOF ;PAST END OF TAPE?
JZ CERROR
SBI ':'
JNZ HREAD ;LOOKING FOR START OF RECORD
;
; START FOUND, CLEAR CHECKSUM
MOV D,A
CALL RBYTE
MOV E,A ;SAVE LENGTH
CALL RBYTE ;HIGH ORDER ADDR
PUSH PSW
CALL RBYTE ;LOW ORDER ADDR
POP B ;HIGH ORDER ADDRESS TO B
MOV C,A ;LOW ORDER ADDRESS TO C
LDA BBOOL
ORA A
JNZ HVBIAS
MVI A,0FFH
STA BBOOL
MVI A,LOW(RWORK)
SUB C
MOV L,A
MVI A,HIGH(RWORK)
SBB B
MOV H,A
SHLD BRWRK ;BRWRK = RWORK-BIAS
MOV A,C
SUI LOW(RWORK)
MOV L,A
MOV A,B
SBI HIGH(RWORK)
MOV H,A
SHLD NBRWRK ;NBRWRK = BIAS-RWORK
HVBIAS:
LHLD BRWRK ;ADDRESS INTO WORK AREA (BIASED)
DAD B ;BIAS ADDRESS IN H,L
;
; IF ON SECOND PASS, THEN ADDRESSES ARE OFF BY ONE PAGE
LDA PASS
ORA A
JZ CHKLEN
; SECOND PASS, DECREMENT ADDRESS TO PREVIOUS PAGE
DCR H
CHKLEN:
; CHECK THE LENGTH FIELD FOR END OF HEX FILE
MOV A,E ;CHECK FOR LAST RECORD
ORA A
JNZ RDTYPE
; END OF HEX INPUT
RET
;
RDTYPE:
CALL RBYTE ;RECORD TYPE = 0
;
; LOAD THE RECORD ON PASS 0, SET REL BITS ON PASS 1
RED1: CALL RBYTE
MOV B,A ;SAVE DATA BYTE FOR COMPARE
LDA PASS
ORA A
JNZ COMP ;COMPARE ON PASS 1
;
; PASS 0, STORE DATA BYTE TO MEMORY
XCHG ;COMPARE WITH MEMORY TOP ADDRESS
PUSH H
LHLD TOP
MOV A,D
SUB H
JC SIZEOK
JNZ SZERR
MOV A,E
SUB L
JNC SZERR
SIZEOK:
POP H
XCHG
MOV M,B
; COMPUTE HIGH ADDRESS
PUSH H
PUSH D
XCHG ;CURRENT ADDRESS TO H,L
LHLD HLOC ;CURRENT HIGH LOCATION
MOV A,L
SUB E
MOV A,H
SBB D
POP D
POP H
JNC RED2 ;NO CARRY IF HLOC HIGH
SHLD HLOC ;NEW HLOC OTHERWISE
JMP RED2
;
COMP: ;PASS 1, COMPUTE RELOCATION BITS
MOV C,M ;GET DATA FROM MEMORY
MOV A,B
ora a
jnz comp1 ; jump if non-zero byte
lda igz
ora a
jnz red2 ; jump if ignoring zeroes on pass 1
mov a,b
comp1:
SUB C ;DIFFERENT?
JZ RED2 ;SKIP IF SAME DATA
PUSH D
PUSH H
; DIFFERENT, MUST BE BY 1
CPI 1
JZ RELOK ;OK TO RELOCATE
CPI -1 ; OR BY -1
JZ RELOK ;ALSO OK TO RELOCATE
; PRINT ERROR IN FORM -
; REL ERROR AT XXXX IMAGE X
LXI D,RELMSG
CALL PRINT
POP D ;ADDRESS
PUSH D
LHLD NBRWRK ;BIASED ADDRESS
DAD D ;REAL ADDRESS TO HL
CALL PADDR ;ADDRESS PRINTED
POP H
PUSH H ;HL READY FOR SETBIT
JMP RELOK
;
; INLINE RELOCATION ERROR MESSAGE
RELMSG: DB CR,LF,'RELOC ERROR AT $'
;
RELOK: CALL SETBIT ;RELOCATION BIT SET/RESET
POP H
POP D
RED2: INX H
DCR E
JNZ RED1 ;FOR ANOTHER BYTE
; OTHERWISE AT END OF RECORD - CHECKSUM
CALL RBYTE
JNZ CERROR
JMP HREAD ;FOR ANOTHER RECORD
;
RBYTE: ;READ ONE BYTE FROM BUFF AT WBP TO REG-A
; COMPUTE CHECKSUM IN REG-D
PUSH B
PUSH H
PUSH D
;
CALL DISKR ;GET ONE MORE CHARACTER
CALL HEXCON ;CONVERT TO HEX (OR ERROR)
;
; SHIFT LEFT AND MASK
RLC
RLC
RLC
RLC
ANI 0F0H
PUSH PSW ;SAVE FOR A FEW STEPS
CALL DISKR
CALL HEXCON
;
; OTHERWISE SECOND NIBBLE OK, SO MERGE
POP B ;PREVIOUS NIBBLE TO REG-B
ORA B
MOV B,A ;VALUE IS NOW IN B TEMPORARILY
POP D ;CHECKSUM
ADD D ;ACCUMULATING
MOV D,A ;BACK TO CS
; ZERO FLAG REMAINS SET
MOV A,B ;BRING BYTE BACK TO ACCUMULATOR
POP H
POP B ;BACK TO INITIAL STATE WITH ACCUM SET
RET
REND:
;NORMAL END OF LOAD
RET
;
;
DISKR: ;DISK READ
PUSH H
PUSH D
PUSH B
;
RDI: ;READ DISK INPUT
LDA DBP
ANI 7FH
JZ NDI ;GET NEXT DISK INPUT RECORD
;
; READ CHARACTER
RDC:
MVI D,0
MOV E,A
LXI H,DBF
DAD D
MOV A,M
CPI DEOF
JZ RRET ;END OF FILE
LXI H,DBP
INR M
JMP RRET
;
NDI: ;NEXT BUFFER IN
MVI C,RDF
LXI D,DFCB
CALL BDOS
ORA A
JNZ DEF
;
; BUFFER READ OK
STA DBP ;STORE 00H
JMP RDC
;
DEF: ;DISK END OF FILE
MVI A,DEOF
RRET:
POP B
POP D
POP H
; TRANSLATE TO UPPER CASE
TRAN:
CPI 7FH ;RUBOUT?
RZ
CPI ('A' OR 010$0000B) ;UPPER CASE A
RC
ANI 101$1111B ;CLEAR UPPER CASE BIT
RET
;
SETBIT:
;SET THE BIT POSITION GIVEN BY H,L TO 1
CALL FINDBYTE
; ROTATE A 1 BIT BY THE AMOUNT GIVEN BY B - 1
MVI A,1
SET0: DCR B
JZ SET1
ORA A ;CLEAR CY
RAL
JMP SET0
;
; BIT IS IN POSITION
SET1: ORA M ;OR'ED TO BIT PATTERN IN MEMORY
MOV M,A ;BACK TO BIT VECTOR
RET
;
FINDBYTE:
; H,L ADDRESSES A BYTE POSITION, CHANGE H,L TO BIT VECTOR
; POSITION, SET B TO NUMBER OF SHIFTS REQUIRED TO SELECT
; PROPER BIT AT RESULTING H,L POSITION
LXI D,-RWORK
DAD D
XCHG ;BIT ADDRESS IN D,E
MOV A,E
ANI 111B ;VALUE X = 0,1,...,7
; CHANGE TO 8-X (8,7,...,1) TO SIMPLIFY BIT SHIFTING LATER
CMA ;VALUE X = -1,-2,...,-8
ADI 9 ;VALUE X = 8,7, ...,1
MOV B,A
MVI C,3 ;SHIFT COUNT IS 3
SHRL: ;SHIFT RIGHT LOOP
XRA A ;CLEAR FLAGS
MOV A,D
RAR
MOV D,A
MOV A,E
RAR
MOV E,A
DCR C
JNZ SHRL
;
; END OF SHIFT, H,L ADDRESS RELATIVE BYTE POSITION
LHLD HLOC ;LAST MEMORY ADDRESS FOR CODE
INX H
DAD D ;ABSOLUTE ADDRESS IS IN H,L
RET
;
PCHAR: ;PRINT CHARACTER IN A
PUSH H
PUSH D
PUSH B
MOV E,A
MVI C,CONOF
CALL BDOS
POP B
POP D
POP H
RET
;
PNIB: ;PRINT NIBBLE IN REG A
ANI 0FH
CPI 10
JNC P10
; <= 9
ADI '0'
JMP PRN
P10: ADI 'A' - 10
PRN: CALL PCHAR
RET
;
PHEX: ;PRINT HEX CHAR IN REG-A
PUSH PSW
RRC
RRC
RRC
RRC
CALL PNIB
POP PSW
CALL PNIB
RET
;
PADDR: ;PRINT ADDRESS IN H,L
MOV A,H
CALL PHEX
MOV A,L
CALL PHEX
RET
;
CRLF: ;CARRIAGE RETURN - LINE FEED
MVI A,CR
CALL PCHAR
MVI A,LF
CALL PCHAR
RET
;
TERMINATE:
;WRITE MODULE TO DISK
LXI D,-(RWORK-1)
LHLD HLOC ;HIGH MODULE ADDRESS
DAD D ;MODULE RELATIVE END IN H,L
SHLD RSIZE ;STORE MODULE SIZE IN RELOCATOR
PUSH H
LXI D,RELEMSG ;REL MOD END
CALL PRINT
POP H
CALL PADDR ;REL MOD END XXXX
LHLD LBYTE ;LAST POSITION TO WRITE
PUSH H
LXI D,-RWORK
DAD D
PUSH H
LXI D,RELSMSG
CALL PRINT
POP H
CALL PADDR ;REL MOD SIZE XXXX
LXI D,RELDMSG
CALL PRINT
LHLD DSIZE
CALL PADDR ;REL DAT SIZE XXXX
POP H
LXI D,RMOD ;D,E ADDRESS FIRST POSITION TO WRITE
WLOOP: MOV A,L
SUB E
MOV A,H
SBB D ;CARRY GENERATED IF D,E > H,L
JC CLOS
; WRITE ANOTHER RECORD
PUSH H
PUSH D ;FIRST AND LAST SAVED
MVI C,DMF ;SET DMA ADDRESS
CALL BDOS
MVI C,WRF ;WRITE TO FILE
LXI D,OFCB
CALL BDOS ;WRITTEN
ORA A
JNZ OFERR
; WRITE OK, INCREMENT DMA ADDRESS
LXI H,128
POP D
DAD D
XCHG
POP H ;STATE RESTORED FOR ANOTHER WRITE
JMP WLOOP
CLOS: ;CLOSE OUTPUT FILE
; MOVE DMA ADDRESS BACK TO 80H SO DATA IS NOT DESTROYED
; (THERE MAY BE A SUBSEQUENT SAVE OF THE ENTIRE MEM IMAGE)
MVI C,DMF
LXI D,DBF
CALL BDOS
MVI C,CLF
LXI D,OFCB
CALL BDOS
CPI 255
JZ OFERR
RET
;
RELEMSG:
DB CR,LF,'REL MOD END $'
RELSMSG:
DB CR,LF,'REL MOD SIZE $'
RELDMSG:
DB CR,LF,'REL DAT SIZE $'
;
HEXCON:
;CONVERT ACCUMULATOR TO PURE BINARY FROM EXTERNAL ASCII
SUI '0'
CPI 10
RC ;MUST BE 0-9
ADI ('0'-'A'+10) AND 0FFH
CPI 16
RC ;MUST BE A-F
LXI D,HEXMSG
CALL PRINT
JMP FINIS
HEXMSG: DB CR,LF,'BAD HEX DIGIT'
INHEX: DB ' '
DB 'IN DATA SIZE SPECIFICATION$'
;
SETUP:
;SETUP FILES FOR PROCESSING
; SCAN FOR DATA SIZE SPECIFICATION
LXI D,DBF
SCNDLR:
LDAX D
INX D
ORA A
JZ NODTSZ
CPI '$'
JNZ SCNDLR
LXI H,0
MVI B,0
ldax d
call tran
cpi 'Z'
jnz scnend
mvi a,0ffh
sta igz
inx d
SCNEND:
LDAX D
INX D
ORA A
JZ ENDTSZ
CALL TRAN ;CONVERT TO UPPER CASE
CALL HEXCON
JNC ENDTSZ
OKDIGIT:
MOV C,A
DAD H
DAD H
DAD H
DAD H
DAD B
JMP SCNEND
NODTSZ:
LXI H,0
ENDTSZ:
LXI D,RMOD
MVI B,0
XRA A
ZEROBP:
STAX D
INX D
DCR B
JNZ ZEROBP
SHLD DSIZE
MVI A,'$'
STA INHEX
; SET DMA ADDRESS TO DBF
LXI D,DBF
MVI C,DMF
CALL BDOS
; LOOK FOR VALID FILE NAMES
LDA DFCB+1
CPI ' '
JZ FNERR
LDA DFCB+17
CPI ' '
JZ FNERR
; NAMES ARE PRESENT, COPY SECOND NAME TO OFCB
LXI H,OFCB
LXI D,DFCB+16
MVI B,16
FLOOP: LDAX D ;GET CHARACTER
MOV M,A
INX H
INX D
DCR B
JNZ FLOOP
;
; NAME COPIED, DELETE CURRENT VERSIONS, MAKE NEW FILE
LXI D,OFCB
PUSH D
MVI C,DLF
CALL BDOS
POP D
MVI C,MKF
CALL BDOS
CPI 255
JZ OFERR
XRA A
STA OFR ;CLEAR RECORD NUMBER
;
; NEW FILE HAS BEEN CREATED, NOW OPEN INPUT FILE
MVI C,OPF ;FILE OPEN FUNCTION
LXI D,DFCB ;FILE CONTROL BLOCK ADDRESS
CALL BDOS
CPI 255 ;ERROR IF NOT FOUND
JZ OPERR ;ERROR MESSAGE AND ABORT IF NOT FOUND
LXI H,DBP ;DATA BUFFER POINTER
MVI M,0 ;CAUSES IMMEDIATE DATA READ
RET
;
OPERR: ;OPEN ERROR
LXI D,OPMSG
CALL PRINT
JMP FINIS
;
OPMSG: DB CR,LF,'INPUT FILE NOT PRESENT$'
;
BERROR:
LXI D,BASMSG
CALL PRINT
JMP FINIS
BASMSG: DB CR,LF,'INVALID RELOCATION BASE$'
;
;
CERROR:
;ERROR IN INPUT, ABORT THE LOAD
LXI D,ERMSG
CALL PRINT
JMP FINIS
ERMSG: DB CR,LF,'BAD INPUT RECORD$'
;
FNERR:
LXI D,FNMSG
CALL PRINT
JMP FINIS
FNMSG: DB 'MISSING FILE NAME$'
;
OFERR:
LXI D,OFMSG
CALL PRINT
JMP FINIS
OFMSG: DB 'CANNOT CREATE OUTPUT FILE$'
;
SZERR:
LXI D,SZMSG
CALL PRINT
JMP FINIS
SZMSG: DB 'HEX FILE SIZE TOO LARGE$'
;
PRINT: ;PRINT MESSAGE ADDRESSED BY D,E
MVI C,PRF
CALL BDOS
RET
;
FINIS: ;END OF PROCESSING
JMP BOOT
;
DBP: DS 1 ;DISK BUFFER POINTER
RBASE: DS 1 ;RELOCATION BASE
PASS: DS 1 ;PASS 0,1
;
;
HLOC: DS 2 ;HIGH ADDRESS IN MODULE
LBYTE: DS 2 ;LAST BIT VECTOR BYTE POSITION
;
;
BRWRK: DS 2 ;BIASED RWORK
NBRWRK: DS 2 ;NEGATIVE BIASED RWORK
;
OFCB: DS 32 ;OUTPUT FILE CONTROL BLOCK
OFR: DS 1 ;OUTPUT FILE RECORD NUMBER
;
DS STKSIZ ;STACK SIZE
STACK:
;
igz: db 0 ;ignore zeroes on pass 1, boolean
BBOOL: DB 0 ;BIAS COMPUTED, BOOLEAN
; ;THIS DB GUARANTEES MODULE SIZE
END