Press enter to see results or esc to cancel.

Calculating Offsets of Code Blocks

This procedure calculates offset of each program code block and total code size.

Procedure CalculateCodeBlockOffsetsAndTotalCodeSize;
Var ProgramCodeBlock: PProgramCodeBlockRecord;
    ProcedureRecordPtr: PProceduresBlockRecord absolute ProgramCodeBlock;
    BlockPtr: PtrRec absolute ProgramCodeBlock;
    UnitCodeSize, NumberOfSegmentReferencesInUnitProgramCode: Word;
    ExeHeaderSize: LongRec;
begin
  UnitPtrRec.Seg := LastLoadedUsedUnit;
  Repeat
    UnitPtr^.CodeSegment := CurrentCodeSegment;
    ProgramCodeBlock := Ptr (UnitPtrRec.Seg, UnitPtr^.BlockOffset [stCodeBlocks]);
    UnitCodeSize := 0;
    While BlockPtr.Ofs <> UnitPtr^.BlockOffset [Succ (stCodeBlocks)] do
      begin
        If ProgramCodeBlock^.Offset <> BlockUnused then
          begin
            ProgramCodeBlock^.Offset := UnitCodeSize;
            Inc (UnitCodeSize, ProgramCodeBlock^.CodeSize);
          end;
        Inc (ProgramCodeBlock);
      end;
    NumberOfSegmentReferencesInUnitProgramCode := UnitPtr^.NumberOfSegmentReferencesInProgramCodeBlocks;
    If UnitPtr^.OverlayedUnitCodeSize <> 0 then
      begin
        UnitPtr^.OverlayedUnitCodeSize := UnitCodeSize;
        UnitCodeSize := (UnitCodeSize + $000F) shr 4;
        Inc (UnitCodeSize, (NumberOfSegmentReferencesInUnitProgramCode + $0007) shr 3);
        If UnitCodeSize > OverlayHeapSize then OverlayHeapSize := UnitCodeSize;
        UnitCodeSize := $20;
        BlockPtr.Ofs := UnitPtr^.BlockOffset [stProcedures];
        While BlockPtr.Ofs <> UnitPtr^.BlockOffset [Succ (stProcedures)] do
          begin
            If ProcedureRecordPtr^.OverlayedProcedureOffset <> 0 then
              begin
                ProcedureRecordPtr^.OverlayedProcedureOffset := UnitCodeSize;
                Inc (UnitCodeSize, 5);
              end;
            Inc (ProcedureRecordPtr);
          end;
        NumberOfSegmentReferencesInUnitProgramCode := 0;
      end;
    UnitPtr^.CodeSize := UnitCodeSize;
    Inc (CurrentCodeSegment, (UnitCodeSize + $000F) shr 4);
    ExeHeaderSize.Long := (NumberOfSegmentReferencesInUnitProgramCode +
                           UnitPtr^.NumberOfSegmentReferencesInTypedConstantsBlocks) * 4 + CurrentRelocationItemOffset;
    If (ExeHeaderSize.WordH <> 0) or (ExeHeaderSize.WordL > $FFF0) then Error (TooManyRelocationItems);
    CurrentRelocationItemOffset := ExeHeaderSize.WordL;
    UnitPtrRec.Seg := UnitPtr^.PreviousUnitSegment;
  until UnitPtrRec.Seg = 0;
  CodeBytes := 16 * LongInt (CurrentCodeSegment);
end;