Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Edited the source code to be less wide

...

The Mpm assembler generates the relocation table, when parsing the source code for compilation of the binary executable code. The relocator routine that is used by Mpm is made available here for convenience:

Code Block
themeEclipse
languagenone
 MODULE relocator
 XDEF relocator, SIZEOF_relocator

; *************************************************************************
;
; This routine will relocate a machine code program.
; A relocation table is placed immediatly after the relocation routine.
;
; The program that is to be relocated and executed are placed immediately
; after the relocation table.
;
; The relocation routine expects IY to point at the start address, entry
; of the relocater. The relocater then calculates the correct origin for
; the relocated program. The BBC BASIC on the Z88 also setups the IY register
; during a BBC BASIC CALL command to execute local machine code.
;
; After completed relocation, the entry of the relocater is patched to
; JP  which jumps directly to the executing program, if the relocated
; code is called again.
;
; The following registers are affected by the initial relocation process:
;         AFBCDEHL/IX../........ same
;         ......../..IY/afbcdehl different
;
; As indicated above the outside world cannot use the alternate registers
; as parameter interface to the relocated program - they are smashed by the
; relocater.
;
.relocator          ex
  af,af'      ex   af,af'          ; preserve AF       ; preserve    AF
        exx                           ; preserve BC, DE, HL
        push iy
        pop  pushhl
iy        ld   bc, #end_relocator-relocator

        popadd  hl,bc                    ; ldabsolute address of bc, #end_relocator-relocatorrelocation table

        ld     e,(hl)
        addinc  hl,bc
        ld   d,(hl)
        ;push absolutede address of relocation table                   ; DE = ldtotal of relocation e,(hl)offset elements
        inc  hl
        ld inc  c,(hl)
        inc   hl
        ld   db,(hl)                   ; total pushsize deof relocation offset elements
        inc  hl
        ;push DEhl = total of relocation offset elements                 ; preserve pointer to incfirst relocation hloffset element
        add  hl,bc
        ld   cb,(hl)h                     inc ; hlHL = pointer to current relocation address
        ld   c,l   ld   b,(hl)                ; BC = ;program total sizeORG, first byte of relocationprogram
offset
elements.relocate_loop
        ex   (sp),hl         inc  hl       ; HL = pointer to relocation offset element
      push hl ld   a,(hl)
        inc  hl        ; preserve pointer to first relocation offset element        ; ready for next relocation offset pointer
      add  hl,bcor   a
        jr         ld   b,h                      ; HL = pointer to current relocation address
                    ld   c,l                      ; BC = program ORG, first byte of program

.relocate_loop           ex   (sp),hl                  ; HL = pointer to relocation offset element
                         ld   a,(hl)
                         inc  hl                       ; ready for next relocation offset pointer
                         or   a
                         jr   nz, byte_offset
.extended_offset         ld   e,(hl)
                         inc  hl
                         ld   d,(hl)                   ; DE = extended offset pointer to next relocation address
                         inc  hl                       ; ready for next relocation offset pointer
                         jr   relocate_address

.byte_offset             ld   d,0
                         ld   e,a                      ; offset pointer to next relocation address
.relocate_address        ex   (sp),hl                  ; HL = pointer to current relocation address
                         add  hl,de                    ; new pointer at memory that contains relocation address
       nz, byte_offset
.extended_offset         
        ld   e,(hl)
        
                inc  hl
                         ld   d,(hl)                   ; DE = extended offset pointer  ex   de,hl
       to next relocation address
        inc  hl       add  hl,bc              ; ready for next relocation offset ;pointer
HL = address relocated to program ORG in BCjr   relocate_address

.byte_offset
        ld   d,0
        exld   dee,hla                      ; offset pointer to ldnext relocation  (hl),d
 address
.relocate_address
        ex   (sp),hl            dec  hl    ; HL = pointer to current relocation address
        add  hl,de    ld   (hl),e             ; new pointer at memory that ;contains update relocatedrelocation address
back to memory      ld   e,(hl)
        inc  hl
      pop  deld   d,(hl)
        ex   de,hl
       ; DEadd = pointerhl,bc to relocation offset                 ; HL = address relocated to program ORG in exBC
  (sp),hl      ex   de,hl
        ;ld HL = index(hl),d
counter        dec  hl
        ld   (hl),e    dec  hl             ; update relocated address back to  memory

 ; update index counter    pop  de                    ld   a,h; DE = pointer to relocation offset
        ex   (sp),hl        or   l       ; HL = index counter
        dec  hl  ; all addresses relocated?                  ; update index counter
    ex   (sp),hl ld   a,h
        or   l  ; index counter back on stack                 ; all addresses relocated?
     push de  ex   (sp),hl                  ; pointerindex tocounter relocation offset back on stack
        push de           jr   nz, relocate_loop        ; pointer to relocation offset back on stack
     pop  af jr   nz, relocate_loop
        pop   af
   pop  af   pop  af                       ; remove redundant variables

; relocation of program completed. Patch the entry of the relocater to JP  that
; jumps directly to the executing program, if the loaded program is executed again.
; Finish with restoring main registers and then execute program.
;
.relocation_finished
           
        ld   (iy+0),$C3
           
        ld   (iy+1),c
 
                  ld   (iy+2),b                 ; patch entry to JP , the relocated program
 
                  exx                           ; swap back to main BC, DE, HL
           
        ex   af,af'                   ; and main AF
           
        jp   (iy)                     ; execute relocated program...
.end_relocator

DEFC SIZEOF_relocator = end_relocator - relocator

; ******************************************************************************
;
; The relocation table is placed here by the Mpm assembler.
; The format of the generated table is:
;
;    total_elements    ds.w 1
;    sizeof_table      ds.w 1
;    patchpointer_0    ds.b 1  --+
;    patchpointer_1    ds.b 1    |
;    ....                        |  sizeof_table
;    ....                        |
;    patchpointer_n    ds.b 1  --+
;
; The first patch pointer is an offset from the start of the program (.routine)
; to the first position of a location that contains a relocatable address.
; The following patchpointers are relative offsets from the current relocated
; address to the next.
; If the offset distance is larger than 255 bytes between two relocatable
; addresses, the following patchpointer is used:
;
;         0,<16bit patchpointer>
;
; which denotes the an offset from the current relocated address to the next.
; The 16 bit patch pointer is stored in the low byte, high byte order.
;

.routine
; the machine code to be relocated is placed immediately after the relocation table