home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
SIMTEL
/
CPMUG
/
CPMUG001.ARK
/
RELOC.ASM
< prev
next >
Wrap
Assembly Source File
|
1984-04-29
|
10KB
|
450 lines
; RELOC.ASM
;
;
; THIS IS A REGENERATED SOURCE TEXT OF THE PROGRAM PORTION OF
; RELOC.COM. IT GENERATES THE SAME CODE (EXACTLY) AS IS FOUND
; IN LOCATIONS 100-102 AND 12C-393 (HEX) OF RELOC.COM. RELOC.COM
; ALSO CONTAINS A COPY OF CP/M, BEGINNING AT 900H, AND A
; RELOCATION TABLE, PRESENTLY BEGINNING AT 2100H.
;
;
ORG 100H
;
; LOCATIONS OF INFORMATION FROM COMMAND LINE, PUT IN DEFAULT BUFFERS
; BY CCP:
;
NAME1 EQU 5DH ;FIRST "FILENAME" (NO. OF K)
NAME2 EQU 6DH ;2ND "FILENAME" (BLANK OR *)
;
ENTRY EQU 5 ;LOCATION OF JUMP TO BDOS
REBOOT EQU 0 ;LOCATION TO JUMP TO FOR REBOOT
SYSTEM EQU 900H ;WHERE RELOC'S COPY OF SYSTEM RESIDES
SERIAL EQU 1300H ;START OF SERIAL NUMBER IN THAT SYSTEM
SIZE EQU 801H ;WHERE LENGTH OF SYSTEM IS STORED
;
;
CR EQU 0DH
LF EQU 0AH
;
;
;
;
FIRST: JMP START
;
;
;
;
ORG 012CH
;
START: LXI SP,800H
;
;
LXI D,NAME1
LDAX D ;GET FIRST CHAR. OF WHAT IS ASSUMED TO BE NO. OF K
CPI ' '
JZ UNSPEC ;JUMP IF NO NUMBER TYPED IN COMMAND
CPI '?'
JZ UNSPEC ;RECOGNIZE BLANK OR QUESTION MARK AS NO-NUMBER
;
;
; IF WE ARE HERE, THERE IS A DECIMAL NUMBER AT 5DH WAITING TO BE READ
;
LXI H,0 ;H WILL CONTAIN THE VALUE OF THE NUMBER
DIGIT: LDAX D ;GET NEXT DIGIT (ASCII)
INX D ;INCREMENT DIGIT POINTER
CPI ' '
JZ TESTNO ;FINISHED GETTING NUMBER IF BLANK OR NULL
ORA A ;TEST FOR NULL (0)
JZ TESTNO
SUI '0' ;SUBTRACT ASCII 0; THIS CONVERTS DIGIT TO NUMBER
CPI 10 ;MAKE SURE IT WAS REALLY A DIGIT (0-9)
JNC INVAL ;JUMP IF NOT
DAD H ;DOUBLE ACCUMULATED VALUE
PUSH H ;SAVE RESULT
DAD H ;DOUBLE IT AGAIN
DAD H ;AND AGAIN
POP B ;NOW GET RESULT SAVE ABOVE AND ADD TO VALUE
DAD B ;WE HAVE NOW MULTIPLIED VALUE BY 10
MOV C,A ;NOW ADD TO IT THE VALUE OF THE NEW DIGIT
MVI B,0
DAD B
JMP DIGIT ;AND GO BACK FOR NEXT DIGIT
;
;
TESTNO: MOV A,H ;GET HIGH BYTE OF NUMBER OF K SPECIFIED
ORA A ;IF IT'S NOT ZERO, NUMBER WAS 256 OR BIGGER
JNZ INVAL ; AND THEREFORE NOT A VALID MEMORY SIZE
MOV A,L ;GET LOW BYTE
CPI 16 ;SYSTEM MUST BE AT LEAST 16K
JC INVAL ; SO ERROR IF <16.
;
;
; NOW MULTIPY NO. OF K BY 1024 TO GET SPECIFIED MEMORY SIZE
;
MVI L,0 ;L WAS SAVED IN A ABOVE
MOV H,A ;THIS MULTIPLIES BY 256
DAD H ;MULTIPLY BY 2
DAD H ;MULTIPLY BY 2 AGAIN
JMP PUTK ;GO TO NEXT SECTION WITH H=MEMORY SIZE IN BYTES
;
;
INVAL: LXI D,INVMSG
CALL MSG ;OUTPUT "INVALID MEMORY SIZE" MESAGE TO CONSOLE
JMP REBOOT ;REBOOT SYSTEM
;
;
INVMSG: DB CR,LF,'INVALID MEMORY SIZE$'
;
;
; COME HERE IF MEMORY SIZE WAS NOT SPECIFIED IN COMMAND LINE
;
UNSPEC: LXI H,0 ;SET UP TO FIND MEMORY SIZE
PAGE: INR H ;POINT TO 1ST LOCATION OF NEXT PAGE
JZ FOUND ;GET OUT OF LOOP IF WE FOUND 256 PAGES OF MEMORY (WHY?)
MOV A,M ;GET 1ST BYTE OF PAGE POINTED TO BY H
CMA ;COMPLEMENT IT
MOV M,A ; AND PUT IT BACK
CMP M ;NOW READ BACK AND COMPARE
CMA ;RESTORE MEMORY BEFORE JUMPING
MOV M,A
JZ PAGE ;KEEP LOOPING IF MEMORY VALID
FOUND: MOV A,H ;L IS STILL ZERO, SO HL IS NUMBER OF BYTES OF MEMORY,
ANI 0FCH ; TRUNCATED TO NEAREST 256. NOW ZERO BITS 0,1 OF H TO
MOV H,A ; TRUNCATE TO A MULTIPLE OF 1024
PUTK: PUSH H ;SAVE TRUNCATED MEMORY SIZE ON STACK
;
LHLD ENTRY+1 ;GET STARTING ADDRESS OF PRESENT BDOS FROM THE JUMP AT LOC. 5
SHLD BDOS ;SAVE IT FOR LATER USE
;
POP H ;GET MEMORY SIZE AGAIN
PUSH H ; BUT LEAVE IT ON STACK TOP
MOV A,H ;TAKE NUMBER OF PAGES AND DIVIDE BY 4 (INTEGER)
RRC ;TO GET NUMBER OF K.
RRC
ANI 3FH
MOV B,A ;SAVE NUMBER OF K IN B
LXI H,CPMMSG+15 ;POINT TO OF NUMBER OF K (ASCII) IN "CONSTRUCTING" MESSAGE TEXT
MVI A,'0' ;SET IT TO ASCII 00
MOV M,A
INX H
MOV M,A
CNVRT1: LXI H,CPMMSG+16 ;LOOP TO CONVERT NO. OF K TO DECIMAL ASCII (2 DIGITS)
INR M ;INCREMENT LOW DIGIT
MOV A,M ;GET ITS NEW VALUE
CPI '9'+1
JC CNV1A ;CONTINUE LOOP IF STILL IN THE RANGE '0' TO '9'
MVI M,'0' ;ELSE SET IT TO ASCII 0 AND INCREMENT HIGH DIGIT.
DCX H
INR M
CNV1A: DCR B ;DECREMENT REMAINDER OF NUMBER BEING CONVERTED
JNZ CNVRT1 ; AND CONTINUE IN LOOP IF NOT YET ZERO
;
;
LXI D,CPMMSG
CALL MSG ;OUTPUT "CONSTRUCTING . . ." MESSAGE TO CONSOLE
;
;
LXI H,SIZE ;GET LENGTH OF SYSTEM IN BYTES
MOV C,M
INX H
MOV B,M
PUSH B ;SAVE LENGTH IN B AND ON STACK
;
;
; SEARCH RELOC'S COPY OF THE SYSTEM FOR THE STRING "K CP/M VERS 1.3". THE
; SEARCH PRESENTLY BEGINS AT 900H AND CONTINUES THROUGH 900+LENGTH
;
;
LXI H,SYSTEM
SEARCH: LXI D,CPMMSG+17
MOV A,B
ORA C
JZ NOFIND ;EXIT IF SEARCH COMPLETED WITHOUT FINDING STRING
DCX B ;DECREMENT SEARCH COUNT AND SAVE ON STACK
PUSH B
;
MVI C,15 ;SET STRING LENGTH FOR COMPARE LOOP
PUSH H ;SAVE CURRENTLY SEARCH ADDRESS ON STACK
COMPR: LDAX D ;LOOP TO COMPARE STRINGS- D POINTS TO ONE, H TO THE OTHER
CMP M
JNZ NEWLOC ;GO TRY NEXT MEMORY POSITION IF COMPARISON FAILED
INX D
INX H
DCR C
JZ GOTIT
JMP COMPR
;
;
;
;
;
DB 1
SYNERR: XRA A
SYNE1: DCR A
JNZ SYNE1
LXI H,76F3H
SHLD BDOS ;PUT "DI,HLT" AT BDOS, WHERE "CALL ENTRY" WILL RETURN
LXI H,SYSCAL
MVI M,0CDH ;CHANGE INSTRUCTION AT SYSCAL FROM "JMP" TO "CALL"
LXI D,SYNMSG-5
LXI H,5
DAD D
XCHG ;THIS GETS "SYNC. ERROR" MESSAGE ADDRESS IN D
JMP MSG ;OUTPUT MESSAGE AND THEN HANG.
;
;
;
;
NEWLOC: POP H ;GET SEARCH POINTER AGAIN
INX H ;INCREMENT IT
POP B ;RESTORE REMAINING SEARCH COUNT
JMP SEARCH ;GO BACK TO LOOK FOR STRING AGAIN
;
;
GOTIT: POP H ;STRING FOUND- GET ITS LOCATION
POP B ;CLEAN UP STACK
DCX H ;POINT TO 2ND DIGIT OF NUMBER OF K IN STRING
LXI D,CPMMSG+16
LDAX D ;GET ASCII NUMBER OF K FROM STRING, AND PUT IT INTO STRING JUST FOUND
MOV M,A
DCX H
DCX D
LDAX D
MOV M,A
;
;
;
;
NOFIND: LXI B,BDOS ;GET LOW BYTE OF CURRENT BDOS ADDRESS
LDAX B
CPI 6 ;THIS BYTE IS NORMALLY 06, BUT IS CHANGED BY DDT AND RESTORED ON RETURN TO SYSTEM
MVI A,0
JNZ SYNC1 ;GIVE SYNCHRONIZATION ERROR IF BYTE IS NOT 06
STAX B ;SET LOW BYTE OF BDOS ADDRESS TO ZERO, SO ADDRESS IS THAT OF SERIAL NUMBER
;
;
;
;
POP B ;GET SYSTEM LENGTH
POP H ;GET MEMORY SIZE IN BYTES
MOV A,L ;SUBTRACT B FROM H TO GET MSIZE-LENGTH
SUB C ; THIS IS ADDRESS NEW SYSTEM WILL RUN FROM
MOV L,A
MOV A,H
SBB B
MOV H,A
SHLD NEWSYS ;SAVE THIS ADDRESS AT NEWSYS AND IN D
XCHG
;
;
;
;
LXI H,SYSTEM ;POINT TO BEGINNING OF SYSTEM LOADED WITH RELOC.COM
PUSH B ;SAVE LENGTH
;
LDA NAME2 ;GET 2ND ITEM IN COMMAND LINE
CPI ' ' ;IF BLANK, SYSTEM IS TO BE PLACED AT ITS EXECUTION ADDRESS
JZ EXEC
DAD B ;SET H TO POINT TO FIRST LOC. AFTER SYSTEM (START OF RELOCATION TABLE)
JMP REL1
;
;
;
;
SYNC1: LXI H,SYNERR ;SET JUMP AT SYNC2 TO GO TO SYNERR
SHLD SYNC2+1
JMP SYNC2
;
;
;
;
; IF 2ND ITEM IN COMMAND WAS BLANK, THEN COME HERE TO MOVE A COPY
; OF THE SYSTEM FROM 900 TO ITS EVENTUAL EXECUTION ADDRESS.
;
;
EXEC: MOV A,B
ORA C
JZ REL1
DCX B
MOV A,M
STAX D
INX D
INX H
JMP EXEC
;
;
;
;
; LOOP TO PERFORM THE RELOCATION.
; MSIZE-LENGTH+100H IS ADDED TO EACH ADDRESS
; MARKED BY A '1' IN THE RELOCATION BIT TABLE.
;
;
REL1: POP B ;GET LENGTH
PUSH H ;SAVE TABLE ADDRESS
LHLD NEWSYS
XCHG ;ADDRESS OF NEW SYSTEM IN D
LXI H,100H
DAD D ;H IS NOW NEWSYS+100H
;
;
LDA NAME2 ;GET 2ND COMMAND ITEM AGAIN
CPI ' '
JZ REL2
LXI D,SYSTEM ;IF NOT A SPACE, SET D TO PUT NEW SYSTEM IN PLACE FOR SYSGEN
REL2: MOV A,B
ORA C
JZ FINISH ;JUMP IF COUNT HAS REACHED ZERO
JMP REL3
;
;
SYNMSG: DB CR,LF,'SYNCRONIZATION ERROR$'
;
;
REL3: DCX B ;DECREMENT BYTE COUNT
MOV A,E ;GET LOW BYTE OF CURRENT ADDRESS IN NEW SYSTEM
ANI 7 ;IF IT IS A MULTIPLE OF 8, WE NEED TO GET ANOTHER
JNZ REL4 ; BYTE OF THE RELOCATION TABLE
XTHL ;GET H=CURRENT ADDRESS IN TABLE
MOV A,M ;GET THE BYTE THERE
INX H ;INCREMENT TABLE ADDRESS
XTHL ;PUT IT BACK ON STACK
MOV L,A
REL4: MOV A,L ;TEST NEXT BIT OF CURRENT TABLE BYTE
RAL
MOV L,A
JNC REL5 ;IF NOT SET, CONTINUE IN LOOP
LDAX D ;GET HIGH BYTE OF ADDRESS AT CURRENT LOCATION IN NEW SYSTEM
ADD H ;ADD HIGH BYTE OF 100H+EXECUTION ADDRESS
STAX D ; AND PUT BACK IN NEW SYSTEM
JMP REL5
REL5: INX D ;POINT TO NEXT BYTE OF NEW SYSTEM
JMP REL2
;
;
;
;
FINISH: POP D ;CLEAN UP STACK
;
;
; COMPARE SERIAL NUMBER OF NEW SYSTEM WITH THAT OF SYSTEM CURRENTLY RUNNING.
;
;
LXI D,SERIAL ;ADDRESS OF SERIAL NUMBER IN RELOC.COM
LHLD BDOS ;ADDRESS OF SERIAL NO. IN CURRENT SYSTEM
MVI C,6 ;LOOP COUNT
SERLP: LDAX D
CMP M
JNZ SYNC1
INX H
INX D
DCR C
JNZ SERLP
;
;
; IF SYSTEM WAS PUT AT EXECUTION ADDRESS, GO THERE
;
LDA NAME2
CPI ' '
JZ SYSGO
;
;
; IF 900-97F IS ALL ZEROES, THEN MOVE THE WHOLE SYSTEM DOWN 80H BYTES
; FROM 980 TO 900
;
;
MVI B,80H
LXI H,SYSTEM
TEST1: MOV A,M
ORA A
JNZ NOMOVE
INX H
DCR B
JNZ TEST1
;
XCHG ;D IS 980H
LHLD SIZE ;GET SYSTEM LENGTH
LXI B,-80H
DAD B
MOV B,H
MOV C,L ;BC = LENGTH-128
LXI H,900H
MOVE: MOV A,B
ORA C
JZ NOMOVE
DCX B
LDAX D
MOV M,A
INX D
INX H
JMP MOVE
;
;
DB 1
SYNC2: JMP SYNC2
;
;
NOMOVE: LXI H,SIZE
MOV C,M
INX H
MOV B,M ;B = LENGTH
LXI H,900H
DAD B
MOV B,H ;C IS ALREADY ZERO- NOW B IS NUMBER OF PAGES IN NEW SYSTEM
;
;
; PUT NUMBER OF PAGES IN THE NEW SYSTEM INTO THE "SAVE NN . . ." MESSAGE TEXT
;
LXI H,ENDMSG+31
MVI A,30H
MOV M,A
INX H
MOV M,A
PUTN: DCR B
JZ PUTK2
LXI H,ENDMSG+32
INR M
MOV A,M
CPI '9'+1
JC PUTN
MVI M,30H
DCX H
INR M
JMP PUTN
;
;
PUTK2: LHLD CPMMSG+15
SHLD ENDMSG+37 ;PUT NO. OF K IN MESSAGE
LXI D,ENDMSG
CALL MSG ;OUTPUT MESSAGE TO CONSOLE
JMP REBOOT ;RETURN TO CP/M
;
;
;
;
ENDMSG: DB CR,LF,'READY FOR "SYSGEN" OR',CR,LF
DB '"SAVE 00 CPM00.COM"$'
;
;
;
;
SYSGO: LXI D,1600H
LHLD NEWSYS
DAD D
PCHL ;JUMP TO NEW SYSTEM
;
;
;
;
MSG: MVI C,9
SYSCAL: JMP ENTRY
BDOS DW 0
NEWSYS DW 0
;
CPMMSG: DB CR,LF,'CONSTRUCTING 00K CP/M VERS 1.3$'
;
;
;
;
END