Listing 1:
A relocator program for use on 8080 systems.
This is a modified version of the relocator program written by Leor Zolman in the July 1977 BYTE.
This relocator will move a source program to any location in memory and fix address references.
Relocations of a source-program block to any address outside the source are performed without overwriting.
The program is designed to run with the Dynamic Debugging Tool (DDT) of the CP/M software system.
If need be, the program can be modified to run without a monitor or with another monitor by changing the contents of hexadecimal memory location 2DCC.
While differing in some details with Zolman's relocator program, it requires the same information and is run in the same manner.
[8080 source
and
Z80 source]
2D00 ORG 2D00H ;SET ORIGIN
2D00 31162E BEGIN: LXI SP,STACK+8 ;INTIALIZE STACK
2D03 2A032E LHLD SBOT ;BOTTOM OF SOURCE
2D06 EB XCHG ;D,E=SBOT=(B)
2D07 2A012E LHLD SSTRT ;H,L=SSTRT=(A)
2D0A 4D MOV C,L
2D0B 44 MOV B,H ;SAVE IN B,C
2D0C CDCD2D CALL COMPH ;COMPLIMENT(A) & ADD 1
2D0F 19 DAD D ;H,L=(B)-(A)=BLOCKSIZE
2D10 E5 PUSH H ;SAVE ON STACK
2D11 2A052E LHLD DTOP ;TOP OF DESTINATION
2D14 EB XCHG ;D,E=DTOP=(C)
2D15 69 MOV L,C
2D16 60 MOV H,B ;H,L=SSTRT
2D17 CDCD2D CALL COMPH
2D1A 19 DAD D ;H,L=(C)-(A)=DISPL
2D1B 220C2E SHLD DISPL ;SAVE DISPLACEMENT
2D1E F5 PUSH PSW ;HAS SIGN OF DISPL
2D1F 3A0B2E LDA FUNC ;CHECK FOR MOVE
2D22 B7 ORA A
2D23 CA602D JZ STEP2 ;IF 0 FIX REF. ONLY
2D26 F1 POP PSW
2D27 DA3E2D JC DOWN ;(C)>(A) IF CARRY SET
;IF COME HERE DESTINATION IS ABOVE SOURCE
;SO MOVE IS DONE HEAD-TO-HEAD
2D2A EB UP: XCHG ;H,L=D,E=DTOP
2D2B D1 POP D ;D,E=BLKSIZE
2D2C 0A X: LDAX B ;B,C=SSTRT=SOURCE PTR.
2D2D 77 MOV M,A ;MOVE TO NEW LOC.
2D2E 7A MOV A,D
2D2F B7 ORA A
2D30 C2382D JNZ Y ;CHECK IF THRU
2D33 7B MOV A,E
2D34 B7 ORA A
2D35 CA582D JZ TEST ;IF D,E=0 THEN MOVE DONE
2D38 23 Y: INX H ;INCR DEST. PTR. TO NEXT
2D39 03 INX B ;INCR SOURCE PTR.
2D3A 1B DCX D ;COUNT DOWN BLKSIZE
2D3B C32C2D JMP X ;CONTINUE
;IF COME HERE DESTINATION IS BELOW SOURCE
;SO MOVE IS DONE TAIL-TO-TAIL
2D3E EB DOWN: XCHG ;H,L=D,E=DTOP
2D3F D1 POP D ;D,E=BLKSIZE
2D40 D5 PUSH D ;SAVE ON STACK
2D41 19 DAD D ;H,L=DBOT=DTOP+BLKSIZE
2D42 EB XCHG ;D,E=DBOT:H,L=BLKSIZE
2D43 09 DAD B ;H,L=SSTRT+BLKSIZE=SBOT
2D44 EB XCHG ;D,E=SBOT:H,L=DBOT
2D45 C1 POP B ;B,C=BLKSIZE
2D46 1A XX: LDAX D ;D,E=SOURCE PTR.
2D47 77 MOV M,A ;MOVE TO NEW LOC.
2D48 78 MOV A,B
2D49 B7 ORA A
2D4A C2522D JNZ YY ;CHECK IF THRU
2D4D 79 MOV A,C
2D4E B7 ORA A
2D4F CA582D JZ TEST ;B,C=0,MOVE DONE
2D52 2B YY: DCX H ;PT. TO NEXT DEST.
2D53 1B DCX D ;PT. TO NEXT SOURCE
2D54 0B DCX B ;COUNT DOWN BLKSIZE
2D55 C3462D JMP XX ;CONTINUE
2D58 3A0B2E TEST: LDA FUNC ;=02 IF MOVE ONLY
2D5B FE02 CPI 02H
2D5D CACC2D JZ DONE
;COME HERE TO DO REFERENCE FIXING.
;NECESSARY ONLY FOR 3 BYTE OP CODES
2D60 01E72D STEP2: LXI B,TABL3 ;B,C= TABLE PTR
2D63 2A032E LHLD SBOT ;NEED TO ADD 1 TO SBOT
2D66 23 INX H
2D67 22032E SHLD SBOT
2D6A 2A072E LHLD START ;D,E=MEMORY PTR.
2D6D EB XCHG
2D6E 2A092E CHEKF: LHLD SSTP ;CHECK FOR END OF FILE
2D71 CDCD2D CALL COMPH ;D,E-MEM. PTR.
2D74 19 DAD D ;D,E-H,L=DIFF.
2D75 DACC2D JC DONE ;DIFF.>=0,CARRY SET
2D78 1A NEXT: LDAX D ;LOAD MEM. USING D,E
2D79 67 MOV H,A ;SAVE IN H
2D7A AF XRA A ;ZERO ACCUM.
2D7B 6F MOV L,A ;SET UP CNTR.
2D7C 2C COMP3: INR L ;BUMP CNTR
2D7D 7D MOV A,L
2D7E FE1B CPI 27D ;CHECK FOR END OF TABLE
2D80 CA8C2D JZ AGAIN ;IF THRU..LOOK @ 2 BYT OPS
2D83 0A LDAX B ;LOAD TABLE ENTRY
2D84 94 SUB H ;COMP. WITH CURR. MEM.
2D85 CAA12D JZ MTCH3 ;JMP IF MATCH
2D88 03 INX B ;ELSE BUMP TABLE PTR.
2D89 C37C2D JMP COMP3 ;LOOK AGAIN
2D8C 01D52D AGAIN: LXI B,TABL2 ;NOW,LOOK AT 2 BYTE OPS
2D8F AF XRA A ;ZERO ACCUM.
2D90 6F MOV L,A ;SET CTR.
2D91 2C COMP2: INR L ;BUMP CTR.
2D92 7D MOV A,L
2D93 FE13 CPI 19D ;CHECK FOR END TABLE
2D95 CAC52D JZ OUT1 ;NO MATCH 2 OR 3 BYTE OPS
2D98 0A LDAX B ;LOAD TABLE ENTRY
2D99 94 SUB H ;COMP. WITH CURRENT MEM.
2D9A CAC42D JZ OUT2 ;JMP IF MATCH
2D9D 03 INX B ;ELSE BUMP TABLE PTR.
2D9E C3912D JMP COMP2 ;LOOK AGAIN
2DA1 2A032E MTCH3: LHLD SBOT ;FOUND 3 BYTE OP CODE
2DA4 CDCD2D CALL COMPH ;IS ADDR. IN RANGE?
2DA7 13 INX D ;GET LO ADDR. BYTE
2DA8 1A LDAX D ;LOAD IN ACC.
2DA9 4F MOV C,A ;STORE IN C
2DAA 13 INX D ;GET HI ADDR. BYTE
2DAB 1A LDAX D ;LOAD ACC.
2DAC 47 MOV B,A ;PUT IN B
2DAD 09 DAD B ;H,L=MEM.ADDR.-SBOT
2DAE DAC52D JC OUT1 ;MEM.ADDR.>=SBOT+1,C SET
2DB1 2A012E LHLD SSTRT ;LESS THAM (A)?
2DB4 CDCD2D CALL COMPH
2DB7 09 DAD B ;H,L=MEM.ADDR.-SSTRT
2DB8 D2C52D JNC OUT1 ;MEM.ADDR. < SSTRT,C=0
2DBB 2A0C2E FIXR: LHLD DISPL ;IF COME HERE,IN RANGE.
2DBE 09 DAD B ;H,L=MEM.ADDR.+DISPL
2DBF 7C MOV A,H
2DC0 12 STAX D ;STORE NEW HI ADDR.
2DC1 1B DCX D ;PT. AT LO ADDR. BYTE
2DC2 7D MOV A,L
2DC3 12 STAX D ;STORE NEW LO ADDR. BYTE
2DC4 13 OUT2: INX D
2DC5 13 OUT1: INX D ;ADV. PTR. TO NEXT OP
2DC6 01E72D LXI B,TABL3 ;RESET TABLE PTR.
2DC9 C36E2D JMP CHEKF ;CONTINUE
2DCC FF DONE: RST 07 ;FINIS,RETURN TO DDT
;***** SUBROUTINE *****
2DCD 7C COMPH: MOV A,H ;SUBROUTINE USED TO
2DCE 2F CMA ;FIND 2'S COMPLIMENT
2DCF 67 MOV H,A ;REPRESENTATION OF
2DD0 7D MOV A,L ;H,L REGISTER PAIR
2DD1 2F CMA
2DD2 6F MOV L,A
2DD3 23 INX H
2DD4 C9 RET
;***** TABLES AND CONSTANTS *****
2DD5 060E16 TABL2: DB 06H,0EH,16H ;TABLE OF 2 BYTE
2DD8 1E262E DB 1EH,26H,2EH ;OP CODES
2DDB 363EC6 DB 36H,3EH,0C6H
2DDE CEDED6 DB 0CEH,0DEH,0D6H
2DE1 DBDEE6 DB 0DBH,0DEH,0E6H
2DE4 EEF6FE DB 0EEH,0F6H,0FEH
2DE7 011121 TABL3: DB 01H,11H,21H ;TABLE OF 3 BYTE
2DEA 222A31 DB 22H,2AH,31H ;OP CODES
2DED 323AC2 DB 32H,3AH,0C2H
2DF0 C3C4CA DB 0C3H,0C4H,0CAH
2DF3 CCCDD2 DB 0CCH,0CDH,0D2H
2DF6 D4DADC DB 0D4H,0DAH,0DCH
2DF9 E2E4EA DB 0E2H,0E4H,0EAH
2DFC ECF2F4 DB 0ECH,0F2H,0F4H
2DFF FAFC DB 0FAH,0FCH
2E01 SSTRT: DS 02H ;SOURCE TOP(A)
2E03 SBOT: DS 02H ;SOURCE BOTTOM(B)
2E05 DTOP: DS 02H ;DESTINATION TOP(C)
2E07 START: DS 02H ;START OF REF. FIXING(D)
2E09 SSTP: DS 02H ;END OF REF. FIXING(E)
2E0B FUNC: DS 01H ;00=REF. FIX ONLY (F)
;02=MOVE ONLY
;01=MOVE & FIX
2E0C DISPL: DS 02H ;DISPLACEMENT
2E0E STACK: DS 08H ;MEM. SPACE FOR STACK