home *** CD-ROM | disk | FTP | other *** search
- PHASE.DOC
- by
- Mike Rubenstein
-
-
- PHASED code
- -----------
-
- One of the limitations of this assembler is the lack of a .PHASE direc-
- tive. This directive causes the assembler to generate addresses for a
- different section of memory for labels than the actual place the code is
- to be loaded. This is important for the Kaypro since when the ROM is
- called, the lower 32K of memory is no longer available. Simply ORGing
- at a higher location later in the program and jumping there will cause
- the entire area of memory between 100H and the end point of the program
- to be saved resulting in a huge .COM file when loaded with LOAD.COM.
-
- There are many ways to phase code and still end up with a reasonable
- sized .COM file. Here I will present two of the most common methods.
-
-
- Label+OFFSET Method
- -------------------
- In order for code to be assembled in one area to run in another our only
- concern is how the addresses are calculated by the assembler. Normally,
- an assembler sets a location counter when it sees an ORG pseudo-op. As
- it produces each byte of the it increments the location counter to cal-
- culate the next address. If it finds a label, it sets the label's ad-
- dress according to this location counter. The programmer has another
- method of setting the address of labels, with EQU. If every label in
- the program takes the form of Label+OFFSET where the offset is a con-
- stant, then the assembler will produce the code to run in high memory
- while creating a file that will load in low memory. The following short
- program which re-loads your monitor ROM from the ROM to RAM illustrates
- this.
-
- ;***********************************************************************
- ;
- ; Rom Save Program
- ; Run and then enter SAVE 16 ROM.COM
- ; ROM.COM will contain object code of your monitor ROM
- ;***********************************************************************
-
- ORG 100h
- ;
- YES EQU 0FFH
- NO EQU 0
- ;
- OLD EQU YES YES if not a Kaypro 10 or 4-84
- ;
- IF OLD
- SYSPRT EQU 1CH Old Kaypro 2's and 4's
- ELSE
- SYSPRT EQU 14H 10's, 4-84's, 2-84's
- ENDIF
- ;
- OFFSET EQU 8000h Offset for calculating high addresses
- ;
- LD DE,HISTRT The destination of the High memory code
- LD HL,LODEND+1 The source code is just beyond this
- ; loader
- LD BC,HIEND-HISTRT The number of bytes to move (end-start)
- LDIR Move it up there
- JP HISTRT Jump to it
- ;
- LODEND NOP To calculate end of loader/start of high
- ; memory code segment
- ;
- HISTRT EQU $+OFFSET Begin using offset
- ;
- IN A,(SYSPRT) Get present sysport data
- SET 7,A Bank select bit
- OUT (SYSPRT),A
- CALL MOVIT Move the code routine
- IN A,(SYSPRT)
- RES 7,A Back to ram bank
- OUT (SYSPRT),A
- CALL TPAMOV Now move to 100H for save
- JP 0 Back to CP/M
- ;
- MOVIT EQU $+OFFSET
- ;
- LD HL,0 Source is at 0 (in ROM )
- LD DE,OFFSET+1000H Load above us
- LD BC,1000h Ppick up 4K (2732)
- LDIR
- RET
- ;
- TPAMOV EQU $+OFFSET
- ;
- LD HL,OFFSET+1000H Destination becomes source
- LD DE,100H Move to TPA start
- LD BC,1000H 4K bytes to move
- LDIR
- RET
- ;
- HIEND EQU $+OFFSET ; end of code to be relocated
- ;
- END
-
- Assemble this program (the source is on the disk as PHASE1.AZM, so you
- don't have to type it in.) Examine the listing file. Notice that the
- assembler generated high memory addresses though the program loads low.
-
-
- Using DDT.COM
- -------------
- With this method you would split the above program into two parts, the
- loader and the code that is to be relocated. You can assemble the load-
- er and pick an arbitrary source address for the code to be relocated
- (say 200h). Then you can assemble the relocatable portion with an high
- ORG, like 8000H. Now you can join the two HEX files together with the
- program DDT.COM, reading in the high portion with an OFFSET. To get the
- offset, use DDT's Hex sum and difference command in the form of:
-
- -H<desired load address>,<ORG address>
-
- The second number will be the OFFSET. The program we wrote above would
- go together like this.
-
-
- ***********************************************************************
- ; LOADER.AZM Loads relocating code to its destination
- ***********************************************************************
- ;
- ORG 100H
- ;
- BYTCNT EQU 100H We can either supply a value here that
- ; we know will load enough code or assem-
- ; ble the high code first and let the as-
- ; sembler give us this value (examine
- ; print file)
- ;
- HISTRT EQU 8000H Where the relocation code goes
- HILOAD EQU 200H Where the other file goes
- ;
- LD DE,HISTRT The destination of the High memory code
- LD HL,HILOAD The source code is just past this loader
- LD BC,BYTCNT The number of bytes to move (end-start)
- LDIR Move it up there
- JP HISTRT Jump to it, memory code segment
- END
-
-
- ***********************************************************************
- ; PHASE2.AZM
- ; Relocate with DDT
- ***********************************************************************
- ;
- YES EQU 0FFH
- NO EQU 0
- ;
- OLD EQU FALSE
- ;
- IF OLD
- SYSPRT EQU 1CH Old Kaypro 2's and fours
- ELSE
- SYSPRT EQU 14H 10's, 4-84's, 2-84's
- ENDIF
- ;
- BYTCNT EQU HIEND-HISTRT
- ;
- ORG 8000h
- ;
- HISTRT IN A,(SYSPRT) Get present sysport data
- SET 7,A Bank select bit
- OUT (SYSPRT),A
- CALL MOVIT Move the code routine
- IN A,(SYSPRT)
- RES 7,A Back to ram bank
- OUT (SYSPRT),A
- CALL TPAMOV Now move to 100H for save
- JP 0 Back to CP/M
- ;
- MOVIT LD HL,0 Source is at 0 (in ROM )
- LD DE,9000H Load above us
- LD BC,1000h Pick up 4K (2732)
- LDIR
- RET
- ;
- TPAMOV LD HL,9000H Destination becomes source
- LD DE,100H Move to TPA start
- LD BC,1000H 4K bytes to move
- LDIR
- RET
- ;
- HIEND EQU $
- ;
- END
-
-
- Now we can use DDT to join the two files:
-
- DDT LOADER.HEX
- -200,8000
-
- -8200 8200 In this case both numbers are the same (we want
- second
- IPHASE2.HEX Prepare to load file
- R8200 Read in with offset
- ^C Exit to CPM
-
- SAVE 1 PHASE3.COM And the com file is created
-
-
- ORGing High (CP/M modifications)
- --------------------------------
- DDT.COM can be used to load .HEX files anywhere in memory despite where
- the load point (ORG) was set. It does this by reading the file in with
- a negative offset with the 'R' command. Usually CP/M is modified by
- saving the SYSGEN image and then overlaying the image with the modified
- section and re-SYSGENing.
-
- Let's say you wrote a new BIOS for your Kaypro. The BIOS for the old
- Kaypros ORGed at FA00H. You assemble it with the assembler with the ORG
- at FA00H. The object file is KBIOS.HEX
-
- If you want to overlay the present bios with your new BIOS immediately
- to see if it works it is done as follows:
-
- Enter DDT by entering
-
- DDT <carriage return>
- IKBIOS.HEX This sets up DDT for a file read.
- R Actually reads the file in and overlays
- your old bios with the binary code.
- ^C Returns you to CP/M and if all is well
- with your new BIOS, you will warm boot
-
- Now you want a permanent copy of your new BIOS on your system tracks.
- Once done, you will be able to copy your new system onto any disk with
- SYSGEN. SYSGEN copies the system into memory but not at the same place
- the system runs. The BIOS image actually begins at 1F80H in the SYSGEN
- image. We must read the file in at 1F80H even though it ORGs at FA00H.
- We can do this with DDT also. First we must save the SYSGEN image to a
- file.
-
- SYSGEN
- KAYPRO SYSGEN V2.2
- SOURCE DRIVE (OR RETURN TO SKIP)a Get the system from A:
- SOURCE ON A THEN RETURN Enter a carriage return
- DESTINATION DRIVE (OR RETURN TO REBOOT) Enter a carriage return
-
- save 40 cpm.com Save it to a file
-
- Now we use DDT to work on it
-
- DDT CPM.COM <carriage return>
- H1F80,FA00 We ask for the sum and difference
- of desired address - load address
- DDT prints this. The second number
- is the offset
- IKBIOS.HEX
- R
- ^C
-
- Now when we return to CP/M we run sysgen to save the new image to system
- tracks.
-
- SYSGEN <carriage return>
- KAYPPRO SYSGEN V2.2
- SOURCE DRIVE (OR RETURN TO SKIP) Enter return, use the memory image
- DESTINATION DRIVE (OR RETURN TO REBOOT) We will put it on B
- DESTINATION ON B THEN RETURN Another return
- FUNCTION COMPLETE
- DESTINATION DRIVE (OR RETURN TO REBOOT) One more return
-
- Now when when we boot with the disk in drive B the new system will be
- loaded.
-
- --------------------------------- end ----------------------------------