Press enter to see results or esc to cancel.

ES:DI Address Loading

Turbo Pascal tries to optimize loading of addresses to ES:DI register pair. For this purpose it uses few intermediate code instructions that track addresses that need to be loaded. The first intermediate code instruction will load local variable address to ES:DI registers.

Procedure Load_ES_DI (LocalVarProcedure: Word; LocalVarDisplacement: Integer; IntermediateCodeToSaveAddress: Word);
begin
  With PIntermediateCodeRecord (IncreaseSymbolTable (stIntermediateCode, 7))^ do
    begin
      RecordType           := icLoad_ES_DI;
      DestinationProcedure := LocalVarProcedure;
      Displacement         := LocalVarDisplacement;
      SaveAddressCode      := IntermediateCodeToSaveAddress;
    end;
end;

Turbo Pascal assumes that the address in the ES:DI register pair will remain unchanged. Everywhere where either ES or DI registers are changed, Turbo Pascal generates intermediate code instruction to indicate that the address is no longer in registers.

Procedure ES_DI_PointerDestroyed;
begin
  PIntermediateCodeRecord (IncreaseSymbolTable (stIntermediateCode, 1))^.RecordType := ic_ES_DI_Destroyed;
end;

At the code generation phase Turbo Pascal goes through all intermediate code instructions for ES:DI loading and removes redundant loads.

  Procedure RemoveRedundant_ES_DI_AddressLoading;
  Var IntermediateCodePointer: PIntermediateCodeRecord;
      IntermediateCodePointerRec: PtrRec absolute IntermediateCodePointer;
      CurrentLoadedAddress_Displacement: Integer;
      CurrentLoadedAddress_Procedure: Word;
  begin
    IntermediateCodePointer := Ptr (SymbolTable [stIntermediateCode].Segment, LastIntermediateCodeSubroutine);
    CurrentLoadedAddress_Displacement := 0;
    CurrentLoadedAddress_Procedure := 0;
    Repeat
      Case IntermediateCodePointer^.RecordType of
        icGoSub: begin
                   Asm
                     MOV    AX, WORD PTR IntermediateCodePointer
                     ADD    AX, 3
                     PUSH   AX
                   end;
                   IntermediateCodePointerRec.Ofs := IntermediateCodePointer^.NewOffset;
                 end;
        icReturn: Asm
                    POP    WORD PTR IntermediateCodePointer
                  end;
        icByte,
        ic12: Inc (IntermediateCodePointerRec.Ofs, 2);
        icWord,
        icSourceLineNumber,
        icSkippedGoSubSaveAddress: Inc (IntermediateCodePointerRec.Ofs, 3);
        icJumpNear,
        icJumpShort: Inc (IntermediateCodePointerRec.Ofs, 8);
        icLabel: begin
                   Inc (IntermediateCodePointerRec.Ofs, 3);
                   CurrentLoadedAddress_Displacement := 0;
                   CurrentLoadedAddress_Procedure := 0;
                 end;
        icReference,
        icReferenceAsmBlock: Inc (IntermediateCodePointerRec.Ofs, 7);
        icLoad_ES_DI: With IntermediateCodePointer^ do
                         begin
                           If (CurrentLoadedAddress_Procedure = DestinationProcedure) and
                              (CurrentLoadedAddress_Displacement = Displacement) then RecordType := ic_ES_DI_Loaded
                             else begin
                                    CurrentLoadedAddress_Procedure := DestinationProcedure;
                                    CurrentLoadedAddress_Displacement := Displacement;
                                    If SaveAddressCode <> 0 then PIntermediateCodeRecord (
                                                    Ptr (IntermediateCodePointerRec.Seg,
                                                         SaveAddressCode))^.RecordType := icGoSub;
                                  end;
                           Inc (IntermediateCodePointerRec.Ofs, 7);
                         end;
        ic_ES_DI_Loaded: With IntermediateCodePointer^ do
                           begin
                             CurrentLoadedAddress_Procedure := DestinationProcedure;
                             CurrentLoadedAddress_Displacement := Displacement;
                             Inc (IntermediateCodePointerRec.Ofs, 7);
                           end;
        ic_ES_DI_Destroyed: begin
                              CurrentLoadedAddress_Displacement := 0;
                              CurrentLoadedAddress_Procedure := 0;
                              Inc (IntermediateCodePointerRec.Ofs);
                            end;
        icEnd: Break;
        {$IFDEF DEBUG}
        else Writeln (#13#10'ERROR: Unknown ic CODE'); { ERROR, not in TPC }
        {$ENDIF}
      end;
    until False;
  end;