.H Copyright (c) 1988-2002, Gary D. Campbell NAME=PASS1 PASS2 CODE=0A00 0A00 NEXT ------------- LINK: PASS1 --------------------- : Code in this module fans out to a P1xx (xx=type of the .OBJ file), : and simply tracks the Code Base Address (in DI). It also flags : each .OBJ file by an XPATCH entry = [@CODE BASE] [ @0 ], and : leaves the default Data Base Address in DBOT. All these entries : help Passes 2 and 3 to track Code and Data as the .OBJ's are scanned. : 0A00 PASS.1 ENTRY 0A00 SI,DS=%(BP+FB) Pointer to File Base (1st .OBJ) 0A03 CALL SET.PARMS 0A06 CS: DI=%HL Default CodeBase (Virtual Address) 0A09 DO CALL SET.PARMS HL = @ for .OBJ type. 0A0C SWAP HL,BP Push addresses 0A0E PUSH %(BP+2) 2nd address = PASS 1 PROC function 0A11 SWAP HL,BP -- Push other parms Above -- 0A13 POP %BP -- Pop local PARMS Here -- 0A16 CALL %%BP Call PROC function for .OBJ type. 0A19 CALL MIN.SI 0A1C* $SI:0 0A1F LOOP UNTIL EQ 0A21 CALL EMIT.XP Emit XPATCH = final Code Base = DI. 0A24+ DI=DI-1 0A25* DI=DI OR 0F 0A29+ DI=DI+1 Set the Default DBOT(2) to the 0A2A %(BP+DBOT)=DI next paragraph after the Code. 0A2D RETURN (Allow address wraparound, not CY) 0A2E SET.PARMS ENTRY 0A2E PUSH BP 0A2F A=$SI 0FB = Old .OBJ Format 0A31 BP=@P.LIST 0Fx = New "Aux" Format 0A34* DO A:$BP 03x = New .OBJ Format 0A37 * IF GE,EXIT (add others as they are developed) 0A39* A=A OR 0F FB is detected 1st, then Fx (x<0B) 0A3B BP=(BP+3) which is mapped to FF, & so forth. 0A3E LOOP 0A40 HL=%(BP+1) EQ: Good Parms; GT: Bad .OBJ type. 0A43 POP BP Return BP unchanged; HL = @Parms. 0A44 RETURN 0A45 P.LIST:=0FB,@OFB,0FF,@OFX,03F,@O3X Descending , @ 0A4E OFB:=@0100,@P1FB,@P2FB,@S2FB 0A56 OFX:=@P3FB,@090 (P3FB continues 0FB list; FX aborts) 0A5A O0X:=@0100,@CRASH,8*0 BigEndian Quad 0A66 O1X:=@0100,@CRASH,8*0 BigEndian Word 0A72 O2X:=@0100,@CRASH,8*0 LittleEndian Quad 0A7E O3X:=@0100,@P13X,@P23X,@S23X,@P33X,@090 (PAD=l.s.b. of last Word) .PAD=10 0A90 P1FB CALL INIT.FB BC=ByteCount; DI=CodeBase 0A93* DO DI=DI+BC 0A95* SI=SI+BC 0A97* $SI:0 0A9A * IF EQ,EXIT 0A9C CALL FIX.FB 0A9F LOOP 0AA1+ SI=SI+2 0AA3 RETURN 0AA4 INIT.FB AA=%(SI+1) Save [Word][Byte] Max Tokens 0AA7 %(BP+TFB)=AA for an FB file type. 0AAA CALL SKIP.SYM 0AAD A=$SI+ 0AAE SWAP AA,BC 0AAF AA=%SI+ Skip TDA (we don't need it in PASS.1) 0AB0 AA=BC 0AB2* BC=BC AND 03F 0AB6* BC=BC-03 0AB9* A::0C0 0ABB IF NZ, 0ABD HL=%SI Here, we have CODE= and/or DATA= 0ABF+ SI=SI+2 We must skip over them & 0AC1+ BC=BC-2 deduct the count. 0AC3* A::080 0AC5 IF NZ, 0AC7 SWAP HL,DI DI = [CODE=] 0AC9* A::040 0ACB * IF ZR,EXIT 0ACD+ SI=SI+2 0ACF+ BC=BC-2 But, ignore a DATA= 0AD1 EMIT.XP PUSH DS 0AD2 PUSH SI 0AD3 SI,DS=%(BP+XPT) 0AD6 %SI=DI Make a 4-byte XPATCH entry 0AD8+ SI=SI+2 [@CODE BASE] [ @0 ] 0ADA %SI=@0 0ADE+ SI=SI+2 0AE0 %(BP+XPT)=SI (PASS3 has its own EMIT.XP used to emit 0AE3 POP SI non-zero entries for each fixup) 0AE4 POP DS 0AE5 RETURN 0AE6 INIT.LST ENTRY 0AE6 A=$SI Begin Local Symbol Table 0AE8* AA=AA AND 0F 0AEB* DO SI=SI+AA (skip 1st entry) 0AED A=$SI Skip subsequent Fx entries. 0AEF* A=A XOR 0F0 0AF1* A::0F0 0AF3 LOOP WHILE ZR 0AF5 %(BP+LST)=SI The Local Symbol Table begins here. 0AF8 %(BP+LST+2)=DS 0AFB SKIP.SYM ENTRY Skip the rest of the L.S.T. 0AFB DO A=$SI 0AFD* AA=AA AND 0F Skip to end of SymTab 0B00 * IF ZR,EXIT & handle 1st fixup 0B02* SI=SI+AA 0B04 LOOP 0B06+ SI=SI+2 0B08 GOTO MIN.SI .PAD=10 0B10*FIX.FB BC=0 0B12 A=$SI+ Load & Test fixup "Key" 0B13 PUSH AA 0B14* A::080 0B16 IF NZ,GOTO @BMP.2 Code or Data Relative Fixup 0B1A* A::040 NIL or External Fixup 0B1C IF NZ, (NIL) 0B1E A=$SI 0B20* A:$(BP+TFB) Is fixup = Word or Byte ? 0B23 IF LE, (Byte = 1-byte fixup) 0B25+BMP.2: SI=SI+1 Word = 2-byte fixup 0B26+ BC=BC+1 0B27+ DI=DI+1 0B28+ DI=DI+1 0B29+ SI=SI+1 0B2A+ BC=BC+1 0B2B POP AA 0B2C BC=~BC 0B2E* AA=AA AND 3F 0B31* BC=BC+AA 0B33 RETURN 0B34 CRASH ENTRY 0B34 POP AA Emit the "crash" message with 0B35 CALL WRITE.HEX the caller's return address. 0B38 SI=@BAD.END (and terminate execution) 0B3B GOTO DSPLY 0B3E WRITE.HEX ENTRY 0B3E ES=CS 0B40 DI=5D 0B43 SWAP A,A' 0B45 CALL HEX2 0B48 SWAP A,A' 0B4A HEX2 PUSH AA 0B4B* LSR A,4 0B4E CALL HEX1 0B51 POP AA 0B52*HEX1 A=A AND 0F 0B54* A=A+090 0B56* DAA 0B57* A=A+CY+040 0B59* DAA 0B5A $DI+=A 0B5B ES: $DI=0 0B5F RETURN .PAD=10 0B70 P13X CALL INIT.LST Sets LST(4) & skips to 1st . 0B73 CALL IF3X 0B76 CALL EMIT.XP BC=ByteCount; DI=CodeBase 0B79* DO DI=DI+BC 0B7B* SI=SI+BC 0B7D* $SI:0 0B80 * IF EQ,EXIT 0B82 A=$SI+ 0B83 BC=AA 0B85* BC=BC AND 3F 0B89+ BC=BC-1 0B8A* A=A AND 0C0 0B8C DE=@SF3X 0B8F CALL A.FCN 0B92 LOOP 0B94+ SI=SI+2 0B96 RETURN 0B97 IF3X ENTRY CALLed for INIT by PASS1 & PASS3. 0B97 %(BP+TDA)=@0 0B9C A=$SI+ Handle leading <@pad>[CODE=fixup] 0B9D BC=AA Return BC=0,SI= 0B9F* BC=BC AND 3F BC>0,SI= 0BA3+ BC=BC-1 0BA4 DE=@F3X 0BA7 GOTO A.FCN 0BAA F3X: =01,@O01,043,@O43,083,@O83,0C5,@OC5,000,@O00 0BB9 SF3X: =000,@NIL3X,040,@FIX3X,0,@C3X 0BC2*O01: $(SI+1)::0F Here we are looking at [xx skip][ Token:K ] 0BC6 IF ZR, We handle it i.f.f. it's a CODE= fixup. 0BC8 A=$SI 0BCA* A::040 0BCC * IF ZR,EXIT 0BCE* A::080 0BD0 * IF NZ,EXIT 0BD2* AA=AA AND 3F [01 skip][ Token:0 ] (a CODE= fixup!) 0BD5* AA=AA-03 0BD8 SWAP AA,BC 0BD9+ SI=SI+1 0BDA AA=%SI+ 0BDB CALL FIND.3X Gets AA=LST(AA) 0BDE SWAP AA,DI update DI (current CODE address) 0BDF RETURN BC = Byte Count to next . .PAD=10 0BF0 O43: CALL DO.PAD 0BF3 GOTO O01 0BF5 O83: CALL DO.TDA 0BF8 GOTO O01 0BFA OC5: CALL DO.PAD 0BFD CALL DO.TDA 0C00 GOTO O01 0C02*O00: A::040 0C04 IF NZ, 0C06 PUSH AA 0C07 CALL DO.PAD 0C0A POP AA 0C0B* A::080 0C0D IF NZ, 0C0F DO.TDA AA=%SI+ TDA is actually = Token:K 0C10+ BC=BC-2 It's the final DBSE allocated 0C12 %(BP+TDA)=AA after all data declarations. 0C15 RETURN (It's used in PASS3). 0C16 DO.PAD CALL DI.PAD 0C19 %(BP+CBSE)=DI 0C1C RETURN 0C1D DI.PAD AA=%SI+ 0C1E+ BC=BC-2 0C20 SET.PAD ENTRY 0C20* DE=0 0C22* DO LSR AA 0C24. CY=~CY 0C25 * IF NC,EXIT 0C27. RL` DE 0C29 LOOP 0C2B* DI=DI OR DE 0C2D+ DI=DI+1 0C2E RETURN 0C2F FIND.3X PUSH DS Finds [D3] Given: 0C30 PUSH SI [D5] AA = Token:X 0C31 SWAP AA,HL Returns AA = Byte/Word, trashes HL,DE 0C32 SI,DS=%(BP+LST) 0C35 DO AA=%(SI+1) 0C38 DE=%(SI+3) 0C3B* $SI:0D5 0C3E IF NE, 0C40* $SI:0D4 0C43 * IF NE,EXIT 0C45 D=0 0C47* ELSE AA=AA XOR HL 0C49* AA::0FFF0 0C4C * IF EQ,EXIT 0C4E A=$SI 0C50* AA=AA AND 0F 0C53 IF ZR,CALL CRASH 0C58* SI=SI+AA 0C5A LOOP 0C5C SWAP AA,DE 0C5D POP SI 0C5E POP DS 0C5F RETURN .PAD=10 0C70+C3X: BC=BC-2 0C72+ SI=SI+2 0C74+W3X: DI=DI+1 0C75+B3X: DI=DI+1 0C76 NIL3X: RETURN 0C77+Q3X: DI=DI+2 0C79 GOTO W3X 0C7B FIX3X: AA=%SI+ 0C7C+ BC=BC-2 0C7E* A=A AND 0F 0C80* A:0C 0C82 IF LT, 0C84* A=A AND 3 0C86 DE=@X3X 0C89 GOTO A.FCN 0C8C X3X: =1,@B3X,2,@W3X,3,@Q3X,0C,@W3X,0D,@Q3X 0C9B =0E,@W3X,0F,@Q3X,0,@CODE.EQ 0CA4 CODE.EQ AA=%(SI-2) 0CA7* A::0C 0CA9 IF ZR, 0CAB CALL FIND.3X 0CAE SWAP AA,DI 0CAF RETURN 0CB0* A::08 0CB2 IF ZR, 0CB4 CALL FIND.3X 0CB7 CALL SET.PAD 0CBA RETURN 0CBB CALL FIND.3X 0CBE PUSH AA 0CBF A=$SI+ 0CC0 BC=AA 0CC2* BC=BC AND 3F 0CC6* BC=BC-03 0CC9 AA=%SI+ 0CCA* A::2 0CCC POP AA 0CCD IF NZ, 0CCF* ASL AA 0CD1* DI=DI+AA 0CD3 RETURN 0CD4 NEXT . 0A00 FB 0A19 MIN.SI 0A2A DBOT 0A4E P2FB 0A4E S2FB 0A56 P3FB 0A7E P23X 0A7E S23X 0A7E P33X 0AA7 TFB 0AD3 XPT 0AF5 LST 0B38 BAD.END 0B3B DSPLY 0B8F A.FCN 0B97 TDA 0C19 CBSE