Re: 63/64 bit version of Delphi's function random( aRange : integer ) : integer; ?
Available news archives: comp.lang.tcl - comp.lang.python - comp.security.firewalls - sci.crypt - comp.lang.php - comp.lang.javascript
Google
 
Web news.hping.org


sci.crypt archive

Re: 63/64 bit version of Delphi's function random( aRange : integer ) : integer; ?

From: Skybuck Flying <spam@hotmail.com>
Date: Fri Apr 28 2006 - 12:30:47 CEST

Well I just had to know the answer to one of my questions before I go do
other stuff...

The question was if an unsigned version of random would be safe ?

The answer it depends on how you look at it and implement the random
function.

If the random function would use signed multiplications it would give
incorrect output ?

Here is the sanity test program ;) =D

*** Begin of Code ***

program RandomSanityCheck;

{

Reverse Enginering Delphi's Random function from assembler back to pure
delphi.

Mostly to create a 63/64 bit version of the same random function ;)

Mission impossible sir !

Need to known the algorithm to make a 64 bit version ;)

Check out Lehmer's pseudo random number generator alghorithm for thez
algorithm hehe.

}

{

version 0.02 created on 28 april 2006 by Skybuck Flying.

This signed vs unsigned shit is driving me crazy.

Time to cut off some crap code and time to test it to death...

ME MUST KNOW THE ANSWER BEFORE I STOP ;)

CANT GET IT OF MY MIND lol.

MUST GO ON hehehehe.

The VENDETTA music is playing now... messing with my concentration..

but this is not so a difficult task no sir bob...

It's just the last straw =D Wieeeeeeeeeeeeeeee.

Can do that with music on ;) Yes sir bob ! =D

Only doubt is int64 multiplication which will always be signed ?!

Delphi lacks unsigned int64 !?

}

{$APPTYPE CONSOLE}

uses
  SysUtils;

// version 0.04 based on version 0.03
// signed version
var
 vSignedRandSeed : integer;

function RandomSignedSanityCheck( ParaRange : integer ) : integer;
type
 TcombinedRegisters = packed record
 case integer of
  0 :
  (
   // if these are changed to integers many errors occur... ! ;)
// EAX : integer;
// EDX : integer;

   EAX : longword;
   EDX : longword;
  );
  1 :
  (
   Large : int64;
  );
 end;
var
 vCombinedRegisters : TcombinedRegisters;
 vLargeEAX : int64;
 vLargeEDX : int64;
begin

 with vCombinedRegisters do
 begin

  // EAX is probably initialized with the parameter of the function.
  EAX := ParaRange;

// PUSH EBX
  // not necessary

// XOR EBX, EBX
  // not necessary

// IMUL EDX,[EBX].RandSeed,08088405H
  EDX := vSignedRandSeed * $08088405;

// INC EDX
  EDX := EDX + 1;

// MOV [EBX].RandSeed,EDX
  vSignedRandSeed := EDX;

// MUL EDX
// EDX:EAX := EAX * EDX;

  // *** problem code, integer overflow ***
// Large := EAX * EDX;

  vLargeEAX := EAX;
  vLargeEDX := EDX;

  Large := vLargeEAX * vLargeEDX;

// MOV EAX,EDX
  Result := EDX;

// POP EBX
  // not necessary
 end;

end;

// version 0.04 based on version 0.03
// unsigned version
var
 vUnsignedRandSeed : longword;

function RandomUnsignedSanityCheck( ParaRange : longword ) : longword;
type
 TcombinedRegisters = packed record
 case integer of
  0 :
  (
   EAX : longword;
   EDX : longword;
  );
  1 :
  (
   Large : int64;
  );
 end;
var
 vCombinedRegisters : TcombinedRegisters;
 vLargeEAX : int64;
 vLargeEDX : int64;
begin

 with vCombinedRegisters do
 begin

  // EAX is probably initialized with the parameter of the function.
  EAX := ParaRange;

// PUSH EBX
  // not necessary

// XOR EBX, EBX
  // not necessary

// IMUL EDX,[EBX].RandSeed,08088405H
  EDX := vUnsignedRandSeed * $08088405;

// INC EDX
  EDX := EDX + 1;

// MOV [EBX].RandSeed,EDX
  vUnsignedRandSeed := EDX;

// MUL EDX
// EDX:EAX := EAX * EDX;

  // *** problem code, integer overflow ***
// Large := EAX * EDX;

  vLargeEAX := EAX;
  vLargeEDX := EDX;

  Large := vLargeEAX * vLargeEDX;

// MOV EAX,EDX
  Result := EDX;

// POP EBX
  // not necessary
 end;

end;

procedure Main;
var
 vTestMeToDeath : longword;
 vDeath : longword;
 vIndication : longword;

 vSignedResult : integer;
 vUnsignedResult : longword;
begin
 vDeath := $FFFFFFFF;

 vIndication := vDeath;

 vIndication := round(vDeath / 1000);

 // engage ;)
 for vTestMeToDeath := 0 to vDeath do
 begin

// if vIndication > 0 then // dirty little hack to prevent division by zero
by mod ??!!?? weird... but ok.
  if vTestMeToDeath mod vIndication = 0 then
  begin
   writeln('progress: ', ( (vTestMeToDeath / vDeath) * 100 ): 3:1, '%' );
  end;

  vSignedResult := RandomSignedSanityCheck( vTestMeToDeath );
  vUnsignedResult := RandomUnsignedSanityCheck( vTestMeToDeath );

  if not CompareMem( @vSignedResult, @vUnsignedResult, 4 ) then
  begin
   writeln('Difference detected at index: ', vTestMeToDeath );
   writeln('Signed result is: ', vSignedResult, ' longword typecast:',
longword(vSignedResult) );
   writeln('Unsigned result is: ', vUnsignedResult, ' longword typecast:',
longword(vUnsignedResult) );
   writeln;
   writeln('press enter to continue');
   readln;
  end;

 end;

 writeln('done.');
 writeln;

 writeln( 'press enter to continue' );
 readln;
end;

begin
 try
  Main;
 except
  on E : Exception do
  begin
   writeln('big fucking error happened:');
   writeln( E.Message );

   writeln( 'press enter to continue' );
   readln;
  end;
 end;
end.

*** End of Code ***

Bye,
  Skybuck.
Received on Mon May 1 02:05:36 2006