Press enter to see results or esc to cancel.

Processing Mem and Port Arrays

Turbo Pascal Provides two ‘virtual’ arrays that provide acces to memory (Mem) and I/O ports (Port). To access memory we need segment and offset. Both parameters are processed and calculated. The segment is put into the ES register while offset is in DI.

Procedure TExpression.Process_Mem;
Var SegmentExpression, OffsetExpression: TExpression;
begin
  GetNextToken;
  TypeDefPtr := PointerFromOffsets (PUnitOffsets (CurrentIdentifierDataPtr)^);
  DataType := TypeDefPtr^.DataType;
  ExpectTokenAndGetNext (Token_LeftBracket);
  SegmentExpression.ExpectIntegerExpression;
  SegmentExpression.CheckOrdinalRange (Ptr (SystemUnitSegment, Word_TypeOffset));
  ExpectTokenAndGetNext (Token_Colon);
  OffsetExpression.ExpectIntegerExpression;
  OffsetExpression.CheckOrdinalRange (Ptr (SystemUnitSegment, Word_TypeOffset));
  ExpectTokenAndGetNext (Token_RightBracket);
  SegmentExpression.Calculate;
  SegmentExpression.LoadExpressionToRegisters (urAX);
  GenerateInstruction_Byte (PUSH_AX);
  OffsetExpression.Calculate;
  OffsetExpression.LoadExpressionToRegisters (urDI);
  GenerateInstruction_Byte (POP_ES);
  ES_DI_PointerDestroyed;
  EndIntermediateCodeSubroutine;
  UsedRegisters := (SegmentExpression.UsedRegisters + OffsetExpression.UsedRegisters) * [urBX, urDX, urCX, urAX];
  LocationData.Flags := [ofsDI, segES];
  Value.Word := 0;
  Value.W12 := 0;
  Value.W14 := 0;
  Location := elMemory;
end;

I/O ports can be accessed for reading and writing. This procedure processes Port expression for reading. There are two versions of this function: 8-bit Port and 16-bit PortW. Both are defined in the bootstrap system table where PortW has identifier data set to 1.

  Procedure Process_Port;
  Var IOCode: Byte;
  begin
    GetNextToken;
    IOCode := $E4 + Byte (CurrentIdentifierDataPtr^);        { $E4:  IN   AL, XX }
                                                             { $E5:  IN   AX, XX }
    ExpectTokenAndGetNext (Token_LeftBracket);
    ExpectIntegerExpression;
    CheckOrdinalRange (Ptr (SystemUnitSegment, Word_TypeOffset));
    ExpectTokenAndGetNext (Token_RightBracket);
    If (Location = elConstant) and (Value.As10Bytes [1] = 0) then
      GenerateInstruction_TwoBytes (IOCode, Value.Byte)
        else begin
               Calculate;
               LoadExpressionToRegisters (urDX);
               GenerateInstruction_Byte (IOCode or $08);     { $EC:  IN   AL, DX }
                                                             { $ED:  IN   AX, DX }
             end;
    EndIntermediateCodeSubroutine;
    DataType := [itUnsigned];
    If IOCode and $01 <> 0 then DataType := [itUnsigned, it16Bit];
    Location := elRegister;
    Include (UsedRegisters, urAX);
    LocationData.Register := rAX;
  end;