AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Random() in PurePascal

Ein Thema von Win32.API · begonnen am 15. Mai 2009 · letzter Beitrag vom 16. Mai 2009
Antwort Antwort
Win32.API

Registriert seit: 23. Mai 2005
312 Beiträge
 
#1

Random() in PurePascal

  Alt 15. Mai 2009, 13:12
Hallo,

ich habe mir gerade die Random-Funktion einmal näher angeschaut und mir sind 2 Fragen in den Sinn gekommen.

Wieso wird EBX auf Null gesetzt, und dann versucht den Speicher von [EBX+@RandSeed] zu lesen? Das XOR ist doch hier vollkommen überflüssig (Bzw. EBX).

Random funktion aus der System.pas:
Delphi-Quellcode:
function Random(const ARange: Integer): Integer;
asm
        PUSH EBX
        XOR EBX, EBX //<<<<<<
        IMUL EDX,[EBX].RandSeed,08088405H
        INC EDX
        MOV [EBX].RandSeed,EDX
        MUL EDX
        MOV EAX,EDX
        POP EBX
end;

Meine übersetzte Funktion gibt andere Werte zurück als die Funktion aus der System.pas. Ich könnte mir Vorstellen, dass es an dem mod liegt. Aber was anderes macht hier doch keinen Sinn, oder?

MUL EDX //EAX := EAX * EDX und EDX = ? Meine Übersetzung:
Delphi-Quellcode:
function MyRandom2(const ARange: Cardinal): Cardinal;
begin
  result := Cardinal(RandSeed * $08088405 + 1) mod aRange;
  RandSeed := result;
end;

Gruß,
Win32
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.121 Beiträge
 
Delphi 12 Athens
 
#2

Re: Random() in PurePascal

  Alt 15. Mai 2009, 13:34
vielleicht ist dir noch nicht aufgefallen, daß RandSeed auch noch verändert wird (sonst würdest du beim nächsten Aufruf deiner Funktion den seben Wert erhalben )

ich hatte mir das mal vor langer Zeit etwa so übersetzt ... glaub ich
Delphi-Quellcode:
Function Random(Range: LongInt): LongInt;
  Begin
    RandSeed := Int64(RandSeed) * 134775813 + 1;
    Result := TLargeIntRec(Int64(Range) * LongWord(RandSeed)).Hi;
  End;
aber was mit EBX ist ... k.A.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Benutzerbild von BUG
BUG

Registriert seit: 4. Dez 2003
Ort: Cottbus
2.094 Beiträge
 
#3

Re: Random() in PurePascal

  Alt 15. Mai 2009, 14:23
Code:
XOR EBX, EBX
entspricht
Code:
MOV EBX, 0
braucht aber weniger Prozessortakte, da 0 nicht erst aus dem Speicher geladen werden muss.

Ob das heute noch Sinn macht: keine Ahnung.

MfG,
Bug
Intellekt ist das Verstehen von Wissen. Verstehen ist der wahre Pfad zu Einsicht. Einsicht ist der Schlüssel zu allem.
  Mit Zitat antworten Zitat
Win32.API

Registriert seit: 23. Mai 2005
312 Beiträge
 
#4

Re: Random() in PurePascal

  Alt 15. Mai 2009, 14:29
Zitat von himitsu:
vielleicht ist dir noch nicht aufgefallen, daß RandSeed auch noch verändert wird (sonst würdest du beim nächsten Aufruf deiner Funktion den seben Wert erhalben )

ich hatte mir das mal vor langer Zeit etwa so übersetzt ... glaub ich
Delphi-Quellcode:
Function Random(Range: LongInt): LongInt;
  Begin
    RandSeed := Int64(RandSeed) * 134775813 + 1;
    Result := TLargeIntRec(Int64(Range) * LongWord(RandSeed)).Hi;
  End;
aber was mit EBX ist ... k.A.
Ja, das mit RandSeed ist mir bewust. Man kann es entweder auskommentieren, oder das Prigramm 2 mal starten (Ohne randomize()). Beides bringt aber nicht das erwartete Ergbenis.

Zitat von BUG:
Code:
XOR EBX, EBX
entspricht
Code:
MOV EBX, 0
braucht aber weniger Prozessortakte, da 0 nicht erst aus dem Speicher geladen werden muss.

Ob das heute noch Sinn macht: keine Ahnung.

MfG,
Bug
Die Begründung das 0 er aus dem Speicher geladen werden müsste ist falsch, und ja es ist auch Heute noch schneller.
  Mit Zitat antworten Zitat
brechi

Registriert seit: 30. Jan 2004
823 Beiträge
 
#5

Re: Random() in PurePascal

  Alt 15. Mai 2009, 14:48
wenn du dir den erstellten Assemblercode anschaust sollte es klar werden:

004035CD 31DB xor ebx,ebx
004035CF 6993087084000584 imul edx,[ebx+$00847008],$08088405


wird wohl schneller sein als ein

mov ebx, randseed
imul edx, ebx, $08088405

-----------
Und bei einem

mov ebx, 0

wird die 0 (0 als opcode parameter) sehr wohl aus dem speicher geladen
  Mit Zitat antworten Zitat
Win32.API

Registriert seit: 23. Mai 2005
312 Beiträge
 
#6

Re: Random() in PurePascal

  Alt 15. Mai 2009, 15:01
Hi brechi,


Zitat von brechi:
wenn du dir den erstellten Assemblercode anschaust sollte es klar werden:

004035CD 31DB xor ebx,ebx
004035CF 6993087084000584 imul edx,[ebx+$00847008],$08088405


wird wohl schneller sein als ein

mov ebx, randseed
imul edx, ebx, $08088405
Kann man es nicht einfach so umschreiben:

Delphi-Quellcode:
xor ebx,ebx
imul edx,[ebx+$00847008],$08088405
->
imul edx,[0 + $00847008],$08088405
->
imul edx,[$00847008],$08088405
Das ist doch bestimmt schneller als erst EBX auf 0 zu setzen und dann nochmal auf EBX lesend zugreifen (Das PUSH/POP nicht zu vergessen).


Zitat von brechi:
bei einem

mov ebx, 0

wird die 0 (0 als opcode parameter) sehr wohl aus dem speicher geladen
Da hast du recht, habe nicht soweit gedacht. Für mich ist es aber kein "echtes" laden, da der OP-Code immer "geladen" werden muss.



Gruß
  Mit Zitat antworten Zitat
gammatester

Registriert seit: 6. Dez 2005
999 Beiträge
 
#7

Re: Random() in PurePascal

  Alt 15. Mai 2009, 18:48
Bei der ganzen Diskussion mit EBX etc ist doch etwas untergangen, warum der Ausgangscode nicht funktioniert und warum nicht mod benutzt wird. Zum ersten war himitsu ziemlich nahe dran. Hier ein Delphiprogramm, daß exakt random reproduziert (zumindest bis D10):
Delphi-Quellcode:
program rt;

{$apptype console}

{$q-,r-}

uses
  windows,sysutils;

var
  myrandseed: cardinal;

function myrandom(range: cardinal): cardinal;
begin
  myrandseed := myrandseed * $08088405 + 1;
  result := (int64(range) * myrandseed) shr 32;
end;

var
  k: integer;
  r1,r2: cardinal;
begin
  myrandseed := randseed;
  for k:=1 to 10 do begin
    r1 := random(100000);
    r2 := myrandom(100000);
    writeln(r1:10, r2:10, myrandseed mod 2:4, myrandseed mod 4:4)
  end;
  readln;
end.
Ausgabe ist:
Code:
 
.        0         0   1   1
.     3137      3137   0   2
.    86104     86104   1   3
.    20258     20258   0   0
.    27292     27292   1   1
.    67165     67165   0   2
.    31869     31869   1   3
.    16179     16179   0   0
.    37223     37223   1   1
.    42567     42567   0   2
Die letzen beiden Spalten zeigen, warum mod nicht 'gut' ist: die unteren Bits sind halt nicht besonders zufällig :)

Selbst random und die hohen Bits haben eine klein Bias, aber für den Hausgebrauch reichts (für wissenschaftliche Zwecke ist die Periode von random eh zu klein, und für Kryptographie sowieso völlig ungeignet).

Gammatester
  Mit Zitat antworten Zitat
Win32.API

Registriert seit: 23. Mai 2005
312 Beiträge
 
#8

Re: Random() in PurePascal

  Alt 16. Mai 2009, 17:09
Hallo gammatester,

danke für die ausführliche Erklärung! Ich hatte verdrengt, dass mul das Ergebnis in edx:eax speichert. Und somit immer mit den falschen 4byte gerechnet.

Delphi-Quellcode:
function MyRandom2(const ARange: Cardinal): Cardinal;
begin
  result := Cardinal(RandSeed * $08088405 + 1) * Int64(ARange) shr 32;
  RandSeed := result;
end;
Gruß,
Win32
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:22 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz