From Gary B. Little's "Apple ProDOS: Advanced Features for Programmers", pages 176 - 188:
"Since the ONLINE command handler is not inherently relocatable, all references to internal absolute addresses must be altered to reflect the change in the position of the code."
I don't understand the address choices in the relocate routine:
STA CMDCODE+$0F and so on.
Why $0F,$1A,$32,$49,#4E,$55,$6F,$75,$8A,$A4,AND $D5. How are these "references to internal absolute addresses".
I'm not getting it and if anyone would be so kind to go through this and explain it to me it would be much appreciated.
I posted the assembler listing in its entirety not knowing what would be required to understand the question
1 **************************************************
2 * BASIC SYSTEM "ONLINE" COMMAND *
3 * *
4 * ONLINE [,Sn] [,Dn] *
5 * *
6 * Copr. 1985 Gary B. Little *
7 **************************************************
8
=003C 9 SBLOCK EQU $3C ;Parameters for block move
=003E 10 EBLOCK EQU $3E
=0042 11 FBLOCK EQU $42
=0073 12 HIMEM EQU $73 ;Use this as ONLINE buffer
13
=0200 14 IN EQU $200 ;Command input buffer
15
=BE06 16 EXTRNCMD EQU $BE06 ;External command JMP instruction
=BE09 17 ERROUT EQU $BE09 ;Error handler
=BE50 18 XTRNADDR EQU $BE50 ;Start of external cmd handler
=BE52 19 XLEN EQU $BE52 ;External cmd name length (-1)
=BE53 20 XCNUM EQU $BE53 ;Command # (0 for external)
=BE54 21 PBITS EQU $BE54 ;Command parameter bits
=BE56 22 FBITS EQU $BE56 ;Parameters found in parse
=BE61 23 VSLOT EQU $BE61 ;Slot parameter specified
=BE62 24 VDRIV EQU $BE62 ;Drive parameter specified
=BEF5 25 GETBUFR EQU $BEF5 ;Get free space
26
=BF00 27 MLI EQU $BF00 ;Entry point to MLI
28
=FD8E 29 CROUT EQU $FD8E ;Print a CR
=FDED 30 COUT EQU $FDED ;Standard character output subroutine
=FE2C 31 MOVE EQU $FE2C ;Block move subroutine
32
34
35 ORG $2000
36
37 * Calculate # of pages that we need to reserve:
38
002000: 38 39 SEC
002001: A9 22 40 LDA #>END
002003: E9 21 41 SBC #>CMDCODE
002005: 8D 74 20 42 STA PAGES
002008: EE 74 20 43 INC PAGES
44
00200B: AD 74 20 45 LDA PAGES ;Reserve the pages for the
00200E: 20 F5 BE 46 JSR GETBUFR : command handler
002011: 90 05 =2018 47 BCC INSTALL ;Clear carry if OK
48
002013: A9 0E 49 LDA #14 ;"PROGRAM TOO LARGE" error
002015: 4C 09 BE 50 JMP ERROUT
51
002018: 8D 75 20 52 INSTALL STA PGSTART ;Save the starting page
53
54 * Install the command handler:
55
00201B: AD 07 BE 56 LDA EXTRNCMD+1 ;Set up link to
00201E: 8D 26 21 57 STA NEXTCMD+1 ; existing external command.
002021: AD 08 BE 58 LDA EXTRNCMD+2
002024: 8D 27 21 59 STA NEXTCMD+2
60
61 **************************************************
62 * Install the external command handler *
63 * by storing its address after the *
64 * JMP at EXTRNCMD *
65 **************************************************
66
002027: A9 00 67 LDA #0
002029: 8D 07 BE 68 STA EXTRNCMD+1
00202C: AD 75 20 69 LDA PGSTART
00202F: 8D 08 BE 70 STA EXTRNCMD+2
71
72 * Relocate the code
73
002032: AD 75 20 74 LDA PGSTART ;Get new page #
002035: 8D 0F 21 75 STA CMDCODE+$0F
002038: 8D 1A 21 76 STA CMDCODE+$1A
00203B: 8D 32 21 77 STA CMDCODE+$32
00203E: 8D 49 21 78 STA CMDCODE+$49
002041: 8D 4E 21 79 STA CMDCODE+$4E
002044: 8D 55 21 80 STA CMDCODE+$55
002047: 8D 6F 21 81 STA CMDCODE+$6F
00204A: 8D 75 21 82 STA CMDCODE+$75
00204D: 8D 8A 21 83 STA CMDCODE+$8A
002050: 8D A4 21 84 STA CMDCODE+$A4
002053: 8D D5 21 85 STA CMDCODE+$D5
86
87 * Set up parameters for block move to final location:
88
002056: A9 00 89 LDA #<CMDCODE
002058: 85 3C 90 STA SBLOCK
00205A: A9 21 91 LDA #>CMDCODE
00205C: 85 3D 92 STA SBLOCK+1
93
00205E: A9 03 94 LDA #<END
002060: 85 3E 95 STA EBLOCK
002062: A9 22 96 LDA #>END
002064: 85 3F 97 STA EBLOCK+1
98
002066: A9 00 99 LDA #0
002068: 85 42 100 STA FBLOCK
00206A: AD 75 20 101 LDA PGSTART
00206D: 85 43 102 STA FBLOCK+1
103
00206F: A0 00 104 LDY #0
002071: 4C 2C FE 105 JMP MOVE ;Move it!
106
002074: 00 107 PAGES DS 1 ;Length of command handler
002075: 00 108 PGSTART DS 1 ;Starting page of command handler
109
002076: 00 00 00 00 110 DS $2100-* ;(Must start on page boundary)
00207A: 00 00 00 00 00 00 00 00
002082: 00 00 00 00 00 00 00 00
00208A: 00 00 00 00 00 00 00 00
002092: 00 00 00 00 00 00 00 00
00209A: 00 00 00 00 00 00 00 00
0020A2: 00 00 00 00 00 00 00 00
0020AA: 00 00 00 00 00 00 00 00
0020B2: 00 00 00 00 00 00 00 00
0020BA: 00 00 00 00 00 00 00 00
0020C2: 00 00 00 00 00 00 00 00
0020CA: 00 00 00 00 00 00 00 00
0020D2: 00 00 00 00 00 00 00 00
0020DA: 00 00 00 00 00 00 00 00
0020E2: 00 00 00 00 00 00 00 00
0020EA: 00 00 00 00 00 00 00 00
0020F2: 00 00 00 00 00 00 00 00
0020FA: 00 00 00 00 00 00
111
=2100 112 CMDCODE EQU *
113
114 **************************************************
115 * This is the command checker. It *
116 * scans the input buffer to see *
117 * if the command has been entered *
118 **************************************************
002100: D8 119 CLD
002101: A0 00 120 LDY #0
002103: A2 00 121 LDX #0
002105: BD 00 02 122 CHKCMD LDA IN,X ;Get command character
002108: E8 123 INX
002109: C9 A0 124 CMP #$A0 ;Is it a blank
00210B: F0 F8 =2105 125 BEQ CHKCMD ; If it is, ignore it
00210D: D9 EE 21 126 CMP CMDNAME,Y ;Same as our command?
002110: F0 0B =211D 127 BEQ CHKCMD1 ;Yes, so branch
002112: C9 E0 128 CMP #$E0 ;Lower case?
002114: 90 0E =2124 129 BCC NOTFOUND ;No, so branch
002116: 29 DF 130 AND #$DF ;Convert to uppercase
002118: D9 EE 21 131 CMP CMDNAME,Y ;OK now?
00211B: D0 07 =2124 132 BNE NOTFOUND ;No, so branch
00211D: C8 133 CHKCMD1 INY
00211E: C0 06 134 CPY #CMDLEN-CMDNAME ;At end?
002120: D0 E3 =2105 135 BNE CHKCMD ;No, so branch
002122: F0 04 =2128 136 BEQ SETRULES ;Yes, so branch
137
002124: 38 138 NOTFOUND SEC ;Set carry to indicate failure
002125: 4C 00 00 139 NEXTCMD JMP $0000 ;(Fill in when installed)
140
002128: 88 141 SETRULES DEY
002129: 8C 52 BE 142 STY XLEN ;Store command length - 1
143
00212C: A9 51 144 LDA #<EXECUTE ;Put address of command handler
00212E: 8D 50 BE 145 STA XTRNADDR ; into XTRNADDR.
002131: A9 21 146 LDA #>EXECUTE
002133: 8D 51 BE 147 STA XTRNADDR+1
148
002136: A9 00 149 LDA #0
002138: 8D 53 BE 150 STA XCNUM ;External cmd number = 0
151
152 * Set up string parsing rules:
153
00213B: A9 10 154 LDA #$10 ;Pathname is optional
00213D: 8D 54 BE 155 STA PBITS
002140: A9 04 156 LDA #$04 ;Slot and drive allowed
002142: 8D 55 BE 157 STA PBITS+1
158
002145: A5 73 159 LDA HIMEM ;Set ON_LINE buffer (at least
002147: 8D EC 21 160 STA BUFFER ; 256 bytes) to free area
00214A: A5 74 161 LDA HIMEM+1 ; beginning at HIMEM
00214C: 8D ED 21 162 STA BUFFER+1
163
00214F: 18 164 CLC ;Clear carry to indicate success
002150: 60 165 RTS
166
167 * BASIC.SYSTEM comes here after it has
168 * successfully parsed the command line:
169
002151: A9 00 170 EXECUTE LDA #0
002153: 8D EB 21 171 STA UNITNUM ;(Assume all volumes)
002156: AD 57 BE 172 LDA FBITS+1 ;Examine result of parse
002159: 29 04 173 AND #$04 ;Slot/drive specified?
00215B: F0 13 =2170 174 BEQ DOCALL ;No, so check everything
00215D: AD 61 BE 175 LDA VSLOT ;Get slot # specified
002160: 0A 176 ASL
002161: 0A 177 ASL
002162: 0A 178 ASL
002163: 0A 179 ASL ;Slot * 16
002164: AE 62 BE 180 LDX VDRIV ;Get drive # specified
002167: E0 02 181 CPX #2 ;Drive 2?
002169: D0 02 =216D 182 BNE SAVEUN ;No, so branch
00216B: 09 80 183 ORA #$80 ;Set "drive 2" bit
00216D: 8D EB 21 184 SAVEUN STA UNITNUM ;Store slot/drive as unit num
185
002170: 20 00 BF 186 DOCALL JSR MLI
002173: C5 187 DFB $C5 ;ONLINE call
002174: EA 21 188 DA OLPARM ;Address of parm table
189
002176: 20 8E FD 190 JSR CROUT
002179: A0 00 191 LDY #0
00217B: 98 192 SCAN TYA
00217C: 48 193 PHA
00217D: B1 73 194 LDA (HIMEM),Y ;Get slot/drive + length
00217F: F0 61 =21E2 195 BEQ SCAN2 ;If $00 then all done
002181: 29 0F 196 AND #$0F ;Isolate length bits
002183: F0 4E =21D3 197 BEQ NEXTNAME ;If 0, then must be error
002185: 48 198 PHA
199
002186: A2 00 200 LDX #0
002188: BD F4 21 201 PRTMSG1 LDA SLOTMSG,X ;Print slot
00218B: F0 06 =2193 202 BEQ PRTNUM1
00218D: 20 ED FD 203 JSR COUT
002190: E8 204 INX
002191: D0 F5 =2188 205 BNE PRTMSG1
206
002193: B1 73 207 PRTNUM1 LDA (HIMEM),Y ;Get slot/drive + length
002195: 29 70 208 AND #$70 ;Isolate slot bits
002197: 4A 209 LSR
002198: 4A 210 LSR
002199: 4A 211 LSR
00219A: 4A 212 LSR ;We now have slot #
00219B: 09 B0 213 ORA #$B0 ;Convert to ASCCI digit
00219D: 20 ED FD 214 JSR COUT
215
0021A0: A2 00 216 LDX #0
0021A2: BD FA 21 217 PRTMSG2 LDA DRIVEMSG,X ;Print drive #
0021A5: F0 06 =21AD 218 BEQ PRTNUM2
0021A7: 20 ED FD 219 JSR COUT
0021AA: E8 220 INX
0021AB: D0 F5 =21A2 221 BNE PRTMSG2
222
0021AD: A2 B1 223 PRTNUM2 LDX #$B1 ;Assume drive 1
0021AF: B1 73 224 LDA (HIMEM),Y
0021B1: 10 02 =21B5 225 BPL PSKIP ;Branch if drive 1
0021B3: A2 B2 226 LDX #$B2 ;Must be drive 2
0021B5: 8A 227 PSKIP TXA
0021B6: 20 ED FD 228 JSR COUT
0021B9: A9 BA 229 LDA #":
0021BB: 20 ED FD 230 JSR COUT
0021BE: A9 A0 231 LDA #$A0
0021C0: 20 ED FD 232 JSR COUT
233
0021C3: 68 234 PLA
0021C4: AA 235 TAX
0021C5: C8 236 PRTNAME INY
0021C6: B1 73 237 LDA (HIMEM),Y ;Get next character in name
0021C8: 09 80 238 ORA #$80 ;Set high bit
0021CA: 20 ED FD 239 JSR COUT ; and display it
0021CD: CA 240 DEX
0021CE: D0 F5 =21C5 241 BNE PRTNAME ;Branch until done
0021D0: 20 8E FD 242 JSR CROUT
243
0021D3: AD EB 21 244 NEXTNAME LDA UNITNUM ;Was only one volume specified?
0021D6: D0 0A =21E2 245 BNE SCAN2 ;Yes, so branch
246
0021D8: 68 247 PLA
0021D9: 18 248 CLC
0021DA: 69 10 249 ADC #16 ;Move to next name
0021DC: A8 250 TAY
0021DD: C0 E0 251 CPY #224 ;At end of table?
0021DF: D0 9A =217B 252 BNE SCAN ;No, so branch
0021E1: 48 253 PHA
254
0021E2: 68 255 SCAN2 PLA
0021E3: 20 8E FD 256 JSR CROUT
0021E6: 18 257 CLC ;CLC ++> no error
0021E7: A9 00 258 LDA #0 ;Error code = 0
0021E9: 60 259 RTS
260
0021EA: 02 261 OLPARM DFB 2 ;Two parameters
0021EB: 00 262 UNITNUM DFB 0 ;Unit number (DSSS0000)
0021EC: 00 00 263 BUFFER DA $0000 ;Device buffer
264
0021EE: CF CE CC C9 265 CMDNAME ASC "ONLINE" ;Eternal command name
0021F2: CE C5
=21F4 266 CMDLEN EQU *
267
0021F4: D3 CC CF D4 268 SLOTMSG ASC "SLOT ",00
0021F8: A0 00
0021FA: AC A0 C4 D2 269 DRIVEMSG ASC ", DRIVE ",00
0021FE: C9 D6 C5 A0 00
270
=2203 271 END EQU *
End Merlin-16 assembly, 515 bytes, 0 errors, 271 lines, 48 symbols.
Elapsed time = 31 seconds.
Symbol table, alphabetical order:
BUFFER =$21EC CHKCMD =$2105 CHKCMD1 =$211D CMDCODE =$2100
CMDLEN =$21F4 CMDNAME =$21EE COUT =$FDED CROUT =$FD8E
DOCALL =$2170 DRIVEMSG=$21FA EBLOCK =$3E END =$2203
ERROUT =$BE09 EXECUTE =$2151 EXTRNCMD=$BE06 FBITS =$BE56
FBLOCK =$42 GETBUFR =$BEF5 HIMEM =$73 IN =$0200
INSTALL =$2018 MLI =$BF00 MOVE =$FE2C NEXTCMD =$2125
NEXTNAME=$21D3 NOTFOUND=$2124 OLPARM =$21EA PAGES =$2074
PBITS =$BE54 PGSTART =$2075 PRTMSG1 =$2188 PRTMSG2 =$21A2
PRTNAME =$21C5 PRTNUM1 =$2193 PRTNUM2 =$21AD PSKIP =$21B5
SAVEUN =$216D SBLOCK =$3C SCAN =$217B SCAN2 =$21E2
SETRULES=$2128 SLOTMSG =$21F4 UNITNUM =$21EB VDRIV =$BE62
VSLOT =$BE61 XCNUM =$BE53 XLEN =$BE52 XTRNADDR=$BE50
Symbol table, numerical order:
SBLOCK =$3C EBLOCK =$3E FBLOCK =$42 HIMEM =$73
IN =$0200 INSTALL =$2018 PAGES =$2074 PGSTART =$2075
CMDCODE =$2100 CHKCMD =$2105 CHKCMD1 =$211D NOTFOUND=$2124
NEXTCMD =$2125 SETRULES=$2128 EXECUTE =$2151 SAVEUN =$216D
DOCALL =$2170 SCAN =$217B PRTMSG1 =$2188 PRTNUM1 =$2193
PRTMSG2 =$21A2 PRTNUM2 =$21AD PSKIP =$21B5 PRTNAME =$21C5
NEXTNAME=$21D3 SCAN2 =$21E2 OLPARM =$21EA UNITNUM =$21EB
BUFFER =$21EC CMDNAME =$21EE CMDLEN =$21F4 SLOTMSG =$21F4
DRIVEMSG=$21FA END =$2203 EXTRNCMD=$BE06 ERROUT =$BE09
XTRNADDR=$BE50 XLEN =$BE52 XCNUM =$BE53 PBITS =$BE54
FBITS =$BE56 VSLOT =$BE61 VDRIV =$BE62 GETBUFR =$BEF5
MLI =$BF00 CROUT =$FD8E COUT =$FDED MOVE =$FE2C