mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-23 03:09:34 +02:00
194 lines
2.6 KiB
ObjectPascal
194 lines
2.6 KiB
ObjectPascal
{ %target=msdos }
|
|
|
|
{ test for i8086 inline assembler near and far ret instructions }
|
|
|
|
{ since testing and detecting near rets miscompiled as far (and vice versa)
|
|
is hard, we don't actually execute the rets, but instead, before each ret,
|
|
we issue an int instruction that calls our own interrupt handler that
|
|
manually disassembles the instruction, checks that it is of the correct type
|
|
and then skips the instruction. }
|
|
|
|
{ this test is Turbo Pascal 7 compatible }
|
|
|
|
program tretf1;
|
|
|
|
{$hugecode off}
|
|
|
|
uses
|
|
dos;
|
|
|
|
{$ifndef FPC}
|
|
type
|
|
FarPointer = Pointer;
|
|
{$endif ndef FPC}
|
|
|
|
{$F-}
|
|
|
|
const
|
|
NearInt = $E7;
|
|
FarInt = $E8;
|
|
|
|
var
|
|
OldNearIntVec: FarPointer;
|
|
OldFarIntVec: FarPointer;
|
|
|
|
procedure Error;
|
|
begin
|
|
Writeln('Error');
|
|
SetIntVec(NearInt, OldNearIntVec);
|
|
SetIntVec(FarInt, OldFarIntVec);
|
|
halt(1);
|
|
end;
|
|
|
|
procedure IntNearHandler(Flags, CS, IP, AX, BX, CX, DX, SI, DI, DS, ES, BP: Word); interrupt;
|
|
var
|
|
opcode: Byte;
|
|
begin
|
|
opcode:=Mem[CS:IP];
|
|
if (opcode<>$C3) and (opcode<>$C2) then
|
|
Error;
|
|
Inc(IP);
|
|
if opcode=$C2 then
|
|
Inc(IP,2);
|
|
end;
|
|
|
|
procedure IntFarHandler(Flags, CS, IP, AX, BX, CX, DX, SI, DI, DS, ES, BP: Word); interrupt;
|
|
var
|
|
opcode: Byte;
|
|
begin
|
|
opcode:=Mem[CS:IP];
|
|
if (opcode<>$CB) and (opcode<>$CA) then
|
|
Error;
|
|
Inc(IP);
|
|
if opcode=$CA then
|
|
Inc(IP,2);
|
|
end;
|
|
|
|
procedure TestAsm1; near; assembler;
|
|
asm
|
|
int NearInt
|
|
ret
|
|
|
|
int NearInt
|
|
ret 17
|
|
end;
|
|
|
|
procedure TestAsm2; far; assembler;
|
|
asm
|
|
int FarInt
|
|
ret
|
|
|
|
int FarInt
|
|
ret 85
|
|
end;
|
|
|
|
procedure TestAsm3; assembler;
|
|
asm
|
|
int NearInt
|
|
ret
|
|
|
|
int NearInt
|
|
ret 17
|
|
end;
|
|
|
|
procedure TestAsm4; assembler;
|
|
asm
|
|
int NearInt
|
|
retn
|
|
|
|
int NearInt
|
|
retn 5
|
|
|
|
int FarInt
|
|
retf
|
|
|
|
int FarInt
|
|
retf 15
|
|
end;
|
|
|
|
procedure TestPas1; near;
|
|
begin
|
|
asm
|
|
int NearInt
|
|
ret
|
|
|
|
int NearInt
|
|
ret 17
|
|
end;
|
|
end;
|
|
|
|
procedure TestPas2; far;
|
|
begin
|
|
asm
|
|
int FarInt
|
|
ret
|
|
|
|
int FarInt
|
|
ret 85
|
|
end;
|
|
end;
|
|
|
|
procedure TestPas3;
|
|
begin
|
|
asm
|
|
int NearInt
|
|
ret
|
|
|
|
int NearInt
|
|
ret 17
|
|
end;
|
|
end;
|
|
|
|
procedure TestPas4;
|
|
begin
|
|
asm
|
|
int NearInt
|
|
retn
|
|
|
|
int NearInt
|
|
retn 5
|
|
|
|
int FarInt
|
|
retf
|
|
|
|
int FarInt
|
|
retf 15
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
GetIntVec(NearInt, OldNearIntVec);
|
|
SetIntVec(NearInt, Ptr(Seg(IntNearHandler),Ofs(IntNearHandler)));
|
|
GetIntVec(FarInt, OldFarIntVec);
|
|
SetIntVec(FarInt, Ptr(Seg(IntFarHandler),Ofs(IntFarHandler)));
|
|
|
|
TestAsm1;
|
|
TestAsm2;
|
|
TestAsm3;
|
|
TestAsm4;
|
|
|
|
TestPas1;
|
|
TestPas2;
|
|
TestPas3;
|
|
TestPas4;
|
|
|
|
asm
|
|
int NearInt
|
|
retn
|
|
|
|
int NearInt
|
|
retn 5
|
|
|
|
int FarInt
|
|
retf
|
|
|
|
int FarInt
|
|
retf 15
|
|
end;
|
|
|
|
Writeln('Ok');
|
|
|
|
SetIntVec(NearInt, OldNearIntVec);
|
|
SetIntVec(FarInt, OldFarIntVec);
|
|
end.
|