Advertisement
sglienke

PatchInt64Multiplication

Mar 29th, 2017
347
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Delphi 4.33 KB | None | 0 0
  1. unit PatchInt64Multiplication;
  2.  
  3. interface
  4.  
  5. implementation
  6.  
  7. {$IF Defined(MSWINDOWS) and not Defined(CPUX64)}
  8. uses
  9.   SysUtils,
  10.   Windows;
  11.  
  12. function GetActualAddr(Proc: Pointer): Pointer;
  13. type
  14.   PAbsoluteIndirectJmp = ^TAbsoluteIndirectJmp;
  15.   TAbsoluteIndirectJmp = packed record
  16.     OpCode: Word;
  17.     Addr: PPointer;
  18.   end;
  19. begin
  20.   Result := Proc;
  21.   if (Proc <> nil) and (PAbsoluteIndirectJmp(Proc).OpCode = $25FF) then
  22.     Result := PAbsoluteIndirectJmp(Proc).Addr^;
  23. end;
  24.  
  25. procedure RedirectFunction(OrgProc, NewProc: Pointer);
  26. type
  27.   TJmpBuffer = packed record
  28.     Jmp: Byte;
  29.     Offset: Integer;
  30.   end;
  31. var
  32.   n: UINT_PTR;
  33.   JmpBuffer: TJmpBuffer;
  34. begin
  35.   JmpBuffer.Jmp := $E9;
  36.   JmpBuffer.Offset := PByte(NewProc) - (PByte(OrgProc) + 5);
  37.   if not WriteProcessMemory(GetCurrentProcess, OrgProc, @JmpBuffer, SizeOf(JmpBuffer), n) then
  38.     RaiseLastOSError;
  39. end;
  40.  
  41. procedure __llmulo_patch;
  42. asm
  43.   test    edx, edx           {Param1-Hi = 0?}
  44.   jne     @@Large            {No, More than one multiply may be needed}
  45.   cmp     edx, [esp+8]       {Param2-Hi = 0?}
  46.   jne     @@Large            {No, More than one multiply may be needed}
  47.   mul     dword ptr [esp+4]  {Only one multiply needed, Set Result}
  48.   and     eax, eax           {Clear Overflow Flag}
  49.   ret     8
  50. @@Large:
  51.   sub     esp, 28            {allocate local storage}
  52.   mov     [esp], ebx         {save used registers}
  53.   mov     [esp+4], esi
  54.   mov     [esp+8], edi
  55.   mov     [esp+12], ebp
  56.   mov     ebx, [esp+32]      {Param2-Lo}
  57.   mov     ecx, [esp+36]      {Param2-Hi}
  58.   mov     esi, edx
  59.   mov     edi, ecx
  60.   sar     esi, 31
  61.   sar     edi, 31
  62.   xor     eax, esi
  63.   xor     edx, esi
  64.   sub     eax, esi
  65.   sbb     edx, esi           {edx:eax (a1:a0) = abs(Param1)}
  66.   xor     ebx, edi
  67.   xor     ecx, edi
  68.   sub     ebx, edi
  69.   sbb     ecx, edi           {ecx:ebx (b1:b0) = abs(Param2)}
  70.   xor     esi, edi           {Sign Flag, 0 if Params have same sign else -1}
  71.   mov     [esp+16], eax      {a0}
  72.   mov     [esp+20], edx      {a1}
  73.   mov     [esp+24], ecx      {b1}
  74.   mul     ebx                {edx:eax (c1:c0) = a0*b0}
  75.   xchg    ebx, edx           {ebx = c1, edx = b0}
  76.   mov     edi, eax           {abs(Result-Lo) = c0}
  77.   xor     ecx, ecx           {Upper 32 bits of 128 bit result}
  78.   xor     ebp, ebp           {Second 32 bits of 128 bit result}
  79.   mov     eax, [esp+20]      {a1}
  80.   mul     edx                {edx:eax (d1:d0) = a1*b0}
  81.   add     ebx, eax           {c1 + d0}
  82.   adc     ebp, edx           {d1 + carry}
  83.   adc     ecx, 0             {Possible carry into Upper 32 bits}
  84.   mov     eax, [esp+16]      {a0}
  85.   mov     edx, [esp+24]      {b1}
  86.   mul     edx                {edx:eax (e1:e0) = a0*b1}
  87.   add     ebx, eax           {abs(Result-Hi) = c1 + d0 + e0}
  88.   adc     ebp, edx           {d1 + e1 + carry}
  89.   adc     ecx, 0             {Possible carry into Upper 32 bits}
  90.   mov     eax, [esp+20]      {a1}
  91.   mov     edx, [esp+24]      {b1}
  92.   mul     edx                {edx:eax (f1:f0) = a1*b1}
  93.   add     ebp, eax           {d1 + e1 + f0 + carry}
  94.   adc     ecx, edx           {f1 + carry}
  95.   or      ecx, ebp           {Overflow if ecx <> 0 or ebp <> 0}
  96.   jnz     @@Overflow
  97.   mov     edx, ebx           {Set abs(Result-Hi)}
  98.   mov     eax, edi           {Set abs(Result-Lo)}
  99.   cmp     edx, $80000000
  100.   jae     @@CheckRange       {Possible Overflow if edx>=$80000000}
  101. @@SetSign:
  102.   xor     eax, esi           {Correct Sign of Result}
  103.   xor     edx, esi
  104.   sub     eax, esi
  105.   sbb     edx, esi
  106.   mov     ebx, [esp]         {restore used registers}
  107.   mov     esi, [esp+4]
  108.   mov     edi, [esp+8]
  109.   mov     ebp, [esp+12]
  110.   add     esp, 28            {Clears Overflow flag}
  111.   ret     8
  112. @@CheckRange:
  113.   jne     @@Overflow         {Overflow if edx>$80000000}
  114.   test    esi, esi           {edx=$80000000, Is Sign Flag=0?}
  115.   jnz     @@SetSign          {No, Result is Ok (-MaxInt64)}
  116. @@Overflow:
  117.   mov     ebx, [esp]         {restore used registers}
  118.   mov     esi, [esp+4]
  119.   mov     edi, [esp+8]
  120.   mov     ebp, [esp+12]
  121.   add     esp, 28
  122.   mov     ecx, $80000000
  123.   dec     ecx                {Set Overflow Flag}
  124.   ret     8
  125. end;
  126.  
  127. function GetSystem__llmulo: Pointer;
  128. asm
  129.   mov eax,offset System.@_llmulo
  130. end;
  131.  
  132. procedure PatchIt;
  133. begin
  134.   RedirectFunction(GetActualAddr(GetSystem__llmulo), @__llmulo_patch);
  135. end;
  136.  
  137. initialization
  138.   PatchIt;
  139. {$IFEND}
  140.  
  141. end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement