home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
cpm
/
utils
/
asmutl
/
reloc23.lbr
/
RELOC.MQC
/
RELOC.MAC
Wrap
Text File
|
1986-05-06
|
10KB
|
286 lines
Name ('RELOCATE')
Title Relocation Module
Subttl Move a program to top of TPA and run it
.Z80
Extrn $MEMRY
;------------------------------------------------------------------------------
;
; R E L O C A T E
; ===============
;
; When linked at the head of a properly structured program, this module
; will move the program to the top of the TPA and transfer control to it.
;
; The program to be relocated MUST start with the following two items in
; the data segment:- (EXCEPTION - see version 2 notes below)
;
; Dseg ;Data segment
;
; $MEMRY::
; defs 2 ;LINK-80 will fill this in.
; ;Used by the relocator module
; ;to determine the length of the
; ;program.
;
; jp ntrypt ;where "ntrypt" is the address
; ;to which the relocator program
; ;will transfer control. The
; ;relocator will replace the
; ;jump address with the address
; ;of the BDOS
;
;
; Version 2 amendments:
; --------------------
;
; This program now supports a variety of destinations for the relocated
; code. The destination information is passed to this module in the
; 4th and 5th bytes by the self-relocating-program generator.
;
; If 5th byte (codest+1) is zero then the relocation is performed as in
; version 1, i.e. the program is moved to the top of free memory and
; executed. If the 4th byte (codest) is 0 then the program is loaded
; just below the BDOS and the BDOS jump at base+5,+6,+7 is modified to
; reflect a smaller TPA size. However, the SRP generator may set (codest)
; to -8 in which case the program is loaded below the CCP and the BDOS
; jump is not modified. This feature is useful for loading SRPs which
; exit to CP/M by returning control to the CCP instead of doing a warm
; boot via a jump to location base+0.
;
; If (codest+1) is 1 then (codest) is assumed to contain a page offset
; from the base of the BDOS (specifically -8, 0 or +14) which causes
; an overlay of the CCP, BDOS or BIOS. The relocator module does not
; transfer control to the relocated code but returns to CP/M via a jump
; to location CCP+3. This facility is particularly useful for generating
; a relocatable BIOS so that you may for example have a system disk with
; a fairly primitive BIOS but have a more sophisticated BIOS (perhaps too
; large to fit on the system tracks of a single-density disk) which loads
; from the data tracks. You can even test such a BIOS without going
; through a system generation!
;
; N.B. IN THIS CASE IT IS NOT NECESSARY TO HAVE A JUMP INSTRUCTION AT
; THE HEAD OF THE RELOCATABLE CODE.
;
; If (codest+1) is 2 or more then this module assumes that you want the
; program relocated to an address of your choosing. The BDOS jump is
; not modified.
;
; VERSION 2.1 16th November 1982
; Corrected CCP entry.
;
; VERSION 2.1 revisited 27th November 1982
; Corrected several problems in exit to CCP and to programs loaded
; below the CCP.
;
; VERSION 2.2 13th February 1984
; Dispensed with 'illegal' Z80 instructions.
;
; VERSION 2.3 30th December 1984
; Added test for system overlays on CP/M+. A warning message is now
; displayed and the user must respond with 'Y' or 'y' to proceed.
; The theory behind this is that such activities are potentially more
; dangerous on (banked) CP/M+ systems. Also, a CCP overlay is rather
; meaningless!
;
; A new version of this program is planned in the near future. It will
; be a bit smarter about such things. I have decided that the idea of
; checking relocation parameters in the relocator module is pretty
; stupid - it is better done in the generator module where so much
; more code space is available!
;
;------------------------------------------------------------------------------
.comment \
-------------------------------------------------------------------------------
COPYRIGHT NOTICE (C) 1982, 1984 John Hastwell-Batten
These programs have been submitted to the public domain via Bill Bolton's STA-
RCPM system and, more recently, via the Tesseract RCPM+ system.
These programs and the accompanying documentation may be freely distributed
in original or modified form so long as a notice giving credit for the method
is retained in the code.
John Hastwell-Batten
Tesseract RCPM+
Dural, NSW
AUSTRALIA
(02) 651-1404
30th December, 1984
Acknowledgement
In testing those relocations which overlay specified portions of CP/M I have
made use of John Woolner's CCP protection scheme obtained via Bill Bolton's
RCPM system. Without the CCP protection the verification of the relocator
module would have been exceedingly difficult as the standard program testing
tools all overlay the CCP which, in the case of the CP/M overlays, the
relocator expects to be intact.
------------------------------------------------------------------------------\
base equ 0 ;(Some CP/Ms start elsewhere)
userdk equ base+4 ;Where CP/M keeps track of current
;user & disk
aseg
org base+100h
@@relocate::
jp $+5 ;Skip over address parameter
codest:
defw 0 ;Default is relocate to just below BDOS
ld (ccpstack),sp ;Save caller's stack pointer
ld sp,ccpstack ;Set up our own
ld de,$memry+2 ;Address of start of code to DE
ld hl,($memry) ;Address of end of code to HL
xor a ;Clear borrow flag and A register
sbc hl,de ;Calculate code length
push hl ;Save code length
sub l ;Set carry if length not a multiple
;of 256
ld a,(base+7) ;BDOS base page number
ld c,a
ld a,(codest) ;Offset from BDOS
sbc a,h ;Form code destination page number
add a,c
ld h,a ;Code destination page number to H
; Having got here, the address calculation will have been in vain if
; a code destination was specified, i.e. if code destination >= 100h.
;
; If code destination >= 200h then the destination is explicit and we
; load it directly from (codest+1,codest). If code destination is in
; the range 100h to 1FFh then (codest) is assumed to be an offset from
; BDOS. (Specifically, -8 to overlay CCP, 0 to overlay BDOS or 14 to
; overlay BIOS)
ld a,(codest+1) ;Get destination address page number
dec a ;Test it
jp m,normal ; 0 => normal relocation
jr z,implicit ; 1 => CCP, BDOS or BIOS overlay
ld hl,(codest) ;>1 => explicit address
jr normal
implicit:
ld c,12 ;Get CP/M version number
call base+5
ld de,proceed ;Set return address
push de
ld a,h ;MP/M flag
or a ;Test it
jr z,danger
ld a,2Fh ;CP/M Plus version 3.0 or more
cp l
jr c,danger
proceed:
ld a,(base+7) ;BDOS base page number
ld c,a
ld a,(codest) ;Add offset (-8 for CCP, 0 for BDOS
add a,c ;or +14 for BIOS)
ld h,a
normal:
ld l,0 ;HL now holds code destination address
pop bc ;Retrieve code length
push hl ;Save copy of address for BDOS entry
push hl ;Another copy for code adjustment
ex de,hl ;Destination address to DE,
;Source address to HL
ld a,d ;Destination page number to A
push bc ;Save code length
ldir ;Move code up to top of TPA
sub 2 ;Form bias
pop bc ;Recover code length
pop ix ;Retrieve pointer to relocated code
push af ;Save bias
@newrel:
ld e,(hl) ;Get relocation flags in E
inc hl ;Point at next 8 flags
ld d,8 ;Counter
@reloc:
rlc e ;Move a relocation flag into carry
jr nc,@asis ;No change if bit is off, otherwise...
pop af ;Retrieve bias
push af ;Save it again
add a,(ix+0) ;Add bias to address
ld (ix+0),a ;Put back new address byte
@asis:
inc ix ;Point at next code byte
dec bc ;Decrement code length
ld a,b ;Test residual code length
or c
jr z,@done ;Exit if finished
dec d ;Count relocation flags
jr z,@newrel ;Get another set if all used up
jr @reloc ;otherwise continue with this lot
@done:
pop af ;Realign stack
ld hl,(base+6) ;Get BDOS vector
pop ix ;Recover address of relocated code
ld e,(ix+1) ;Get program entry point to DE
ld d,(ix+2)
ld a,(codest+1) ;Get code destination indicator
dec a ;Explicit or implicit destination?
jr z,@CCP ;If relocation overlayed CCP, BDOS
;or BIOS then simply exit to the CCP
ld (ix+1),l ;Fix up the JP at the start of the code
ld (ix+2),h
jp p,@enter ;If explicit destination then don't
;modify the BDOS jump
ld a,(codest) ;Check if relocated under CCP
or a
jr nz,@enter ;If so, leave BDOS jump alone
ld (base+6),ix ;Otherwise, mark new TPA size
@enter:
pop hl ;Here we deliberately underflow our own
ld sp,hl ;stack to pick up the stack pointer as
;it was when we started. This is to
;make the relocation invisible to those
;programs which RETurn to the CCP
;instead of ending with a warm boot.
ex de,hl ;New start address to HL
jp (hl) ;Transfer to relocated program
danger:
ld de,warning ;Display a message saying that what
ld c,9 ;we are doing is very dangerous
call base+5 ;with this version of the operating
ld c,1 ;system and ask for permission to
call base+5 ;proceed.
and 5Fh
cp 'Y'
ret z ;Continue if authorised
jp 0 ;Otherwise stop before we do any damage
@CCP: ld a,(userdk) ;Get current user number (high order
; four bits) & disk number (low-order)
ld c,a ;.... then to C for CCP entry
ld hl,(base+6) ;Get BDOS address
ld l,0 ;Align to page boundary
ld de,3-800h ;Offset to CCP entry
add hl,de ;Address of CCP warm boot entry
jp (hl) ;Exit to CCP
warning:
defb 'CP/M+ & MP/M OVERLAYS ARE DANGEROUS'
defb 13,10,"Continue? $"
;We can't use our caller's stack 'cause
defw 0,0 ;we may overlay it and by the time our
defw 0,0 ;stack overruns the message we won't
;need it.
ccpstack:
defw 0 ;Temporary hidey-hole for our caller's
;stack pointer. (Ordinarily, our
;caller would be the CCP.)
end