TITLE 'CP/M VERSION 2.2 SYSTEM RELOCATOR - 2/80' ; CPM RELOCATOR PROGRAM, INCLUDED WITH THE MODULE TO PERFORM ; THE MOVE FROM 900H TO THE DESTINATION ADDRESS ; ; COPYRIGHT (C) 1979 ; DIGITAL RESEARCH ; BOX 579, PACIFIC GROVE CALIFORNIA ; 93950 ; ORG 100H JMP PASTCOPY COPY: DB 'COPYRIGHT (C) DIGITAL RESEARCH, 1979 ' PASTCOPY: BIOSWK EQU 03H ;THREE PAGES FOR BIOS WORKSPACE STACK EQU 800H MODSIZ EQU 801H ;MODULE SIZE IS STORED HERE VERSION EQU 22 ;CPM VERSION NUMBER BOOTSIZ EQU 100H ;SIZE OF THE COLD START LOADER ; (MAY HAVE FIRST 80H BYTES = 00H) BDOSL EQU 0800H ;RELATIVE LOCATION OF BDOS BIOS EQU 1600H ;RELATIVE LOCATION OF BIOS ; BOOT EQU 0000H ;REBOOT LOCATION BDOS EQU 0005H PRNT EQU 9 ;PRINT BUFFER FUNCTION FCB EQU 5CH ;DEFAULT FCB MODULE EQU 900H ;MODULE ADDRESS ; CR EQU 0DH LF EQU 0AH LXI SP,STACK ; ; MAY BE MEMORY SIZE SPECIFIED IN COMMAND LXI D,FCB+1 LDAX D CPI ' ' JZ FINDTOP CPI '?' ;WAS * SPECIFIED? JZ FINDTOP ; ; MUST BE MEMORY SIZE SPECIFICATION LXI H,0 CLOOP: ;CONVERT TO DECIMAL LDAX D INX D CPI ' ' JZ ECON ORA A JZ ECON ; MUST BE DECIMAL DIGIT SUI '0' CPI 10 JNC CERROR ; DECIMAL DIGIT IS IN A DAD H ;*2 PUSH H DAD H ;*4 DAD H ;*8 POP B ;*2 IN B,C DAD B ;*10 IN H,L MOV C,A MVI B,0 DAD B ;*10+X JMP CLOOP ECON: ;END OF CONVERSION, CHECK FOR PROPER RANGE MOV A,H ORA A JNZ CERROR MOV A,L CPI 16 JC CERROR MVI L,0 MOV H,A DAD H ;SHL 1 DAD H ;SHL 2 FOR KILOBYTES ; H,L HAVE TOP OF MEMORY+1 JMP SETASC ; CERROR: LXI D,CONMSG CALL PRINT JMP BOOT CONMSG: DB CR,LF,'INVALID MEMORY SIZE$' ; ; ; FIND END OF MEMORY FINDTOP: LXI H,0 FINDM: INR H ;TO NEXT PAGE JZ MSIZED ;CAN OVERFLOW ON 64K SYSTEMS MOV A,M CMA MOV M,A CMP M CMA MOV M,A ;BITS INVERTED FOR RAM OPERATIONAL TEST JZ FINDM ; BITS DIDN'T CHANGE, MUST BE END OF MEMORY ; ALIGN ON EVEN BOUNDARY MSIZED: MOV A,H ANI 1111$1100B ;EVEN 1K BOUNDARY MOV H,A SETASC: ;SET ASCII VALUE OF MEMORY SIZE PUSH H ;SAVE FOR LATER ; **** SERIALIZATION **** LHLD BDOS+1 SHLD SER1 ; **** SERIALIZATION **** POP H PUSH H MOV A,H RRC RRC ANI 11$1111B ;FOR 1K COUNTS JNZ NOT64 ;MAY BE 64 K MEM SIZE MVI A,64 ;SET TO LITERAL IF SO NOT64: MOV B,A ;READY FOR COUNT DOWN LXI H,AMEM MVI A,'0' MOV M,A INX H MOV M,A ;BOTH ARE SET TO ASCII 0 ASC0: LXI H,AMEM+1 ;ADDRESS OF ASCII EQUIVALENT INR M MOV A,M CPI '9'+1 JC ASC1 MVI M,'0' DCX H INR M ASC1: DCR B ;COUNT DOWN BY KILOBYTES JNZ ASC0 LXI D,MEMSG CALL PRINT ;MEMORY SIZE MESSAGE ; LXI H,MODSIZ MOV C,M INX H MOV B,M ;B,C CONTAINS MODULE SIZE PUSH B ;MODULE SIZE STACKED ON MEM SIZE ; ; TRY TO FIND THE ASCII STRING 'K CP/M VER X.X' TO SET SIZE LXI H,MODULE ; B,C CONTAINS MODULE LENGTH SLOOP: ;SEARCH LOOP LXI D,AMSG MOV A,B ORA C JZ ESEAR ;END OF SEARCH DCX B ;COUNT SEARCH LENGTH DOWN PUSH B MVI C,LAMSG ;LENGTH OF SEARCH MESSAGE PUSH H ;SAVE BASE ADDRESS OF SEARCH CHLOOP: ;CHARACTER LOOP, MATCH ON CONTENTS OF D,E AND H,L LDAX D CMP M JNZ NOMATCH INX D ;TO NEXT SEARCH CHARACTER INX H ;TO NEXT MATCH CHARACTER DCR C ;COUNT LENGTH DOWN JZ FSEAR ;FOUND SEARCH STRING JMP CHLOOP ; ; **** SERIALIZATION **** DB LXI ;CONFUSE DISASSEMBLER BADSER: ;BAD SERIAL NUMBER, LOOP TO CONFUSE ICE-80 XRA A BADSER0: DCR A JNZ BADSER0 ; LXI H,DI OR (HLT SHL 8) SHLD PRHLT LXI H,PRJMP MVI M,CALL ;CHANGE JMP BDOS TO CALL LXI D,SYNCMSG-5 LXI H,5 DAD D ;TO CONFUSE SEARCHES ON ADDRESSES XCHG JMP PRINT ; **** SERIALIZATION **** ; NOMATCH: ;NOT FOUND AT THIS ADDRESS, LOOK AT NEXT ADDRESS POP H INX H POP B ;RECALL MODULE LENGTH JMP SLOOP ; FSEAR: ;FOUND STRING, SET MEMORY SIZE POP H ;START ADDRESS OF STRING BEING MATCHED POP B ;CLEAR B,C WHICH WAS STACKED DCX H LXI D,AMEM+1 LDAX D MOV M,A DCX H DCX D LDAX D MOV M,A ; END OF FILL ; ESEAR: ;END OF SEARCH ; **** SERIALIZATION **** ; CHECK FOR LEAST SIGNIFICANT BYTE OF 06 IN SER1 LXI B,SER1 LDAX B CPI 6 MVI A,0 JNZ SETJMP ;BAD SERIALIZATION IF NOT 06 STAX B ;STORE 00 TO LEAST SIGNIFICANT BYTE ; **** SERIALIZATION **** POP B ;RECOVER MODULE LENGTH POP H ;H,L CONTAINS END OF MEMORY PUSH B ;SAVE LENGTH FOR RELOCATION BELOW MOV A,B ADI BIOSWK ;ADD BIOS WORK SPACE TO MODULE LENGTH MOV B,A MOV A,L SUB C ;COMPUTE MEMTOP-MODULE SIZE MOV L,A MOV A,H SBB B MOV H,A ; H,L CONTAINS THE BASE OF THE RELOCATION AREA SHLD RELBAS ;SAVE THE RELOCATION BASE XCHG ;MODULE BASE TO D,E LXI H,MODULE;READY FOR THE MOVE POP B ;RECOVER ACTUAL MODULE LENGTH PUSH B ;SAVE FOR RELOCATION LDA FCB+17 ;CHECK FOR NO MOVE CONDITION CPI ' ' JZ MOVE ; SECOND PARAMETER SPECIFIED, LEAVE THE DATA AT 'MODULE' DAD B ;MOVE H,L TO BIT MAP POSITION JMP RELOC ; ; **** SERIALIZATION **** SETJMP: LXI H,BADSER ;BAD SERIALIZATION SHLD JMPSER+1 ;FILL JUMP INSTRUCTION JMP JMPSER ;EVENTUAL JUMP TO MESSAGE ; **** SERIALIZATION **** ; MOVE: MOV A,B ;BC=0? ORA C JZ RELOC DCX B ;COUNT MODULE SIZE DOWN TO ZERO MOV A,M ;GET NEXT ABSOLUTE LOCATION STAX D ;PLACE IT INTO THE RELOC AREA INX D INX H JMP MOVE ; RELOC: ;STORAGE MOVED, READY FOR RELOCATION ; HL ADDRESSES BEGINNING OF THE BIT MAP FOR RELOCATION POP B ;RECALL MODULE LENGTH PUSH H ;SAVE BIT MAP BASE IN STACK LHLD RELBAS XCHG LXI H,BOOTSIZ DAD D ;TO FIND BIAS VALUE ; REGISTER H CONTAINS BIAS VALUE ; ; RELOCATE AT 'MODULE' IF SECOND PARAMETER GIVEN LDA FCB+17 CPI ' ' JZ REL0 ; ; IMAGE NOT MOVED, ADJUST VALUES AT 'MODULE' LXI D,MODULE REL0: MOV A,B ;BC=0? ORA C JZ ENDREL ; **** SERIALIZATION **** JMP PASTSYNC SYNCMSG: DB CR,LF,'SYNCRONIZATION ERROR$' PASTSYNC: ; **** SERIALIZATION **** ; ; NOT END OF THE RELOCATION, MAY BE INTO NEXT BYTE OF BIT MAP DCX B ;COUNT LENGTH DOWN MOV A,E ANI 111B ;0 CAUSES FETCH OF NEXT BYTE JNZ REL1 ; FETCH BIT MAP FROM STACKED ADDRESS XTHL MOV A,M ;NEXT 8 BITS OF MAP INX H XTHL ;BASE ADDRESS GOES BACK TO STACK MOV L,A ;L HOLDS THE MAP AS WE PROCESS 8 LOCATIONS REL1: MOV A,L RAL ;CY SET TO 1 IF RELOCATION NECESSARY MOV L,A ;BACK TO L FOR NEXT TIME AROUND JNC REL2 ;SKIP RELOCATION IF CY=0 ; ; CURRENT ADDRESS REQUIRES RELOCATION LDAX D ADD H ;APPLY BIAS IN H STAX D JMP REL2 ; REL2: INX D ;TO NEXT ADDRESS JMP REL0 ;FOR ANOTHER BYTE TO RELOCATE ; ENDREL: ;END OF RELOCATION POP D ;CLEAR STACKED ADDRESS ; **** SERIALIZATION **** LXI D,MODULE+BDOSL+BOOTSIZ ;ADDRESSING NEW SERIAL NUMBER LHLD SER1 ;ADDRESSING HOST SERIAL NUMBER MVI C,6 ;LENGTH OF SERIAL NUMBER CHKSER: LDAX D CMP M JNZ SETJMP INX H INX D DCR C JNZ CHKSER ; **** SERIALIZATION **** ; LDA FCB+17 CPI ' ' JZ TRANSFER ; DON'T GO TO THE LOADED PROGRAM, LEAVE IN MEMORY ; MAY HAVE TO MOVE THE PROGRAM IMAGE DOWN 1/2 PAGE MVI B,128 ;CHECK FOR 128 ZEROES LXI H,MODULE TR0: MOV A,M ORA A JNZ TREND INX H DCR B JNZ TR0 ; ; ALL ZERO FIRST 1/2 PAGE, MOVE DOWN 80H BYTES XCHG ;NEXT TO GET IN D,E LHLD MODSIZ LXI B,-128 DAD B ;NUMBER OF BYTES TO MOVE IN H,L MOV B,H MOV C,L ;TRANSFERRED TO B,C LXI H,MODULE;DESTINATION IN H,L TRMOV: MOV A,B ORA C ;ALL MOVED? JZ TREND DCX B LDAX D MOV M,A ;ONE BYTE TRANSFERRED INX D INX H JMP TRMOV ; ; ; **** SERIALIZATION **** DB LXI JMPSER: JMP JMPSER ;ADDRESS FIELD FILLED-IN ; **** SERIALIZATION **** ; TREND: ;SET ASCII MEMORY IMAGE SIZE LXI H,MODSIZ MOV C,M INX H MOV B,M LXI H,MODULE;B,C MODULE SIZE, H,L BASE DAD B MOV B,H ;B CONTAINS NUMBER OF PAGES TO SAVE+1 LXI H,SAVMEM;ASCII MEMORY SIZE MVI A,'0' MOV M,A INX H MOV M,A ; '00' STORED INTO MESSAGE TRCOMP: DCR B JZ TRC1 LXI H,SAVMEM+1 ;ADDRESSING LEAST DIGIT INR M MOV A,M CPI '9'+1 JC TRCOMP MVI M,'0' DCX H INR M JMP TRCOMP ; FILL CPMXX.COM FROM SAVMEM TRC1: LHLD AMEM SHLD SAVM0 ; MESSAGE SET, PRINT IT AND REBOOT LXI D,RELOK CALL PRINT JMP BOOT RELOK: DB CR,LF,'READY FOR "SYSGEN" OR' DB CR,LF,'"SAVE ' SAVMEM: DB '00 CPM' SAVM0: DB '00.COM"$' ; TRANSFER: ; GO TO THE RELOCATED MEMORY IMAGE LXI D,BOOTSIZ+BIOS ;MODULE LHLD RELBAS ;RECALL BASE OF RELOC AREA DAD D ;INDEX TO 'BOOT' ENTRY POINT PCHL ;GO TO RELOCATED PROGRAM ; ; **** SERIALIZATION **** PRINT: MVI C,PRNT PRJMP: JMP BDOS PRHLT: ; ; DATA AREAS SER1: DS 2 ;SERIAL NUMBER ADDRESS FOR HOST RELBAS: DS 2 ;RELOCATION BASE MEMSG: DB CR,LF,'CONSTRUCTING ' AMEM: DB '00' AMSG: DB 'k CP/M vers ' DB VERSION/10+'0','.',VERSION MOD 10 +'0' LAMSG EQU $-AMSG ;LENGTH OF MESSAGE DB '$' ;TERMINATOR FOR MESSAGE END