home *** CD-ROM | disk | FTP | other *** search
- PHASED code
-
- One of the limitations of this assembler is the lack of a .PHASE directive.
- 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 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 calculate
- the next address. If it finds a label, it sets the label's address 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 constant, 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
-
- TRUE EQU 0FFH
- FALSE EQU 0
-
- OLD EQU TRUE ; TRUE IF NOT 10 OR 4-84
-
- IF OLD
- SYSPRT EQU 1CH ; old kaypro 2's and fours
- ELSE
- SYSPRT EQU 14H ; tens, 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 ; pick 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 loader
- 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. (8000H say).
- Now you can join the two HEX files together with 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 assemble
- ; the high code first and let the assembler
- ; 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 beyond 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 ***
- ;**************************************************************************
-
- TRUE EQU 0FFH
- FALSE EQU 0
-
- OLD EQU FALSE
-
- IF OLD
- SYSPRT EQU 1CH ; old kaypro 2's and fours
- ELSE
- SYSPRT EQU 14H ; tens, 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
- H200,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 CPM is modified by saving the SYSGEN
- image and then overlaying the image with the modified section and
- re-SYSGENing.
-
- Lets 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 CPM 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.
-