Contributor: GEORGE KALEMANIS { George KalemanisPATCH.PAS - Patching Turbo's Runtime Library On The Fly } Unit patch; Interface {$R-,S-,I- } Function CPUOk : Boolean; InLine( { Sort out 8086/8088 from 80286/i386/i486 } 31ドル/$C0/ { XOR AX, AX } 50ドル/ { PUSH AX } 9ドルD/ { POPF } 9ドルC/ { PUSHF } 58ドル/ { POP AX } { If the flag register holds $F000, then it is a 8086/8088 } 25ドル/00ドル/$F0/ { AND AX, $F000 } 3ドルD/00ドル/$F0/ { CMP AX, $F000 } 74ドル/10ドル/ { JE @@1 } { Sort out 80286 from 80386/80486 } $B8/00ドル/$F0/ { MOV AX, $F000 } 50ドル/ { PUSH AX } 9ドルD/ { POPF } 9ドルC/ { PUSHF } 58ドル/ { POP AX } { If the flag register 2, then it is a 80286 } 25ドル/00ドル/$F0/ { AND AX, $F000 } 74ドル/04ドル/ { JZ @@1 } $B0/01ドル/ { MOV AL, True } $EB/02ドル/ { JMP Short @@2 } $B0/00ドル); { @@1: MOV AL, False } { @@2: } Implementation Const dummy : LongInt = 1; Type SystemProc = Procedure; SystemCall = ^SystemProc; { Pointer to the caller's address } Var CallAddr : ^SystemCall; { Pointer to the procedure to be patched } { Copy instruction pointer of caller from the stack } Function IPtr : Word; InLine( 8ドルB/46ドル/02ドル); { MOV AX, [BP+2] } { This patch speeds up 4-byte signed integer division by 600% } Procedure DivisionPatch; Const PatchCode : Array[0..21] of Byte = ( { Push dividend on the stack, pop it in a 32-bits register To avoid division by zero errors, extend it to a quadword } 52,ドル { PUSH DX } 50,ドル { PUSH AX } 66,ドル 58,ドル { POP EAX } 66,ドル 99,ドル { CDQ } { Push divisor on the stack, pop it in a 32-bit register. Perform the division } 53,ドル { PUSH BX } 51,ドル { PUSH CX } 66,ドル 5ドルE, { POP ESI } 66,ドル $F7, $FE, { IDIV ESI } { Push remainder on the stack, pop it in 16-bits registers } 66,ドル 52,ドル { PUSH EDX } 59,ドル { POP CX } 5ドルB, { POP BX } { Push quotient on the stack, pop it in 16-bits registers } 66,ドル 50,ドル { PUSH EAX } 58,ドル { POP AX } 5ドルA, { POP DX } $CB); { RETF } Begin CallAddr := Ptr(CSeg, IPtr-14); Move(PatchCode, CallAddr^^, SizeOf(PatchCode)); end; { LongIntDivisionPatch } { Provided the product> 2^16, this patch speeds up 4-byte signed integer multiplication by 5% } Procedure MultiplyPatch; Const PatchCode : Array[0..15] of Byte = ( { Push first operand on the stack, pop it in a 32-bits register } 52,ドル { PUSH DX } 50,ドル { PUSH AX } 66,ドル 58,ドル { POP EAX } { Push second operand on the stack, pop it in a 32-bits register Perform the multiplication } 53,ドル { PUSH BX } 51,ドル { PUSH CX } 66,ドル 5ドルA, { POP EDX } 66,ドル $F7, $EA, { IMUL EDX } { Push product on the stack, pop it in 16-bits registers } 66,ドル 50,ドル { PUSH EAX } 58,ドル { POP AX } 5ドルA, { POP DX } $CB); { RETF } Begin CallAddr := Ptr(CSeg, IPtr-14); Move(PatchCode, CallAddr^^, SizeOf(PatchCode)); end; { MultiplyPatch } { Shift directly across multiple words, rather than in a loop } Procedure ShiftLeftPatch; Const PatchCode : Array[0..3] of Byte = ( 0ドルF, $A5, $C2, { SHLD DX, AX, CL } $CB); { RETF } Begin CallAddr := Ptr(CSeg, IPtr-14); Move(PatchCode, CallAddr^^, SizeOf(PatchCode)); end; { ShiftLeftPatch } { Shift directly across multiple words, rather than in a loop } Procedure ShiftRightPatch; Const PatchCode : Array[0..3] of Byte = ( 0ドルF, $AD, $C2, { SHRD DX, AX, CL } $CB); { RETF } Begin CallAddr := Ptr(CSeg, IPtr-14); Move(PatchCode, CallAddr^^, SizeOf(PatchCode)); end; { ShiftRightPatch } Begin { Patch } If CPUOk Then { It's a 32-bitter } Begin dummy := dummy div dummy; DivisionPatch; dummy := dummy*dummy; MultiplyPatch; dummy := dummy shl 1; ShiftLeftPatch; dummy := dummy shr 1; ShiftRightPatch; end; end. { Patch }