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;