Zitat von
sakura:
Und anschließend teste noch folgende, welche imo die schnellste sein sollte:
Delphi-Quellcode:
function VectorSetValue(
const Value:Single): TVector3D;
asm
mov edx, Value
mov [eax], edx
mov [eax + $04], edx
mov [eax + $08], edx
end;
Deren Ergebnis ist i.A. identisch zur Pascal-Lösung, verzichtet aber auf das wiederholte Laden des Übergabewertes.
Bei dieser Lösung sollte man aber bedenken, dass sich durch eine Änderung am record TVector3D evtl. die Adressen ändern.
Beisp:
Delphi-Quellcode:
type
TVector3D = record x, y, z: Single; end;
Dann funktioniert sakuras Lösung.
Delphi-Quellcode:
type
TVector3D = record x, nein_tu_das_nicht, y, z: Single; end;
Ups, nun haben sich die Adressen geändert.
Delphi-Quellcode:
function VectorSetValue(
const Value:Single): TVector3D;
asm
mov edx, Value
mov [eax], edx
mov [eax + $08], edx
mov [eax + $0c], edx
end;
Das ganze ist nun um 4 Byte verschoben, da single 4 Byte belegt.
Werden andere Typen verwendet z.B. Double statt Single, dann sind die Adressen auch entsprechend anders.
Das Delphi aus dem Original Quelltext macht, lässt sich sehr leicht mit dem CPU Fenster ermitteln.
Delphi-Quellcode:
type
TVector3D = record x, y, z: Single; end;
function VectorSetValue(const Value:Single): TVector3D;
begin // <- hier Haltepunkt setzen (F5 Taste)
Result.X := Value;
Result.Y := Value;
Result.Z := Value
end;
procedure TForm1.Button1Click(Sender: TObject);
var
x: TVector3D;
begin
x := VectorSetValue(1);
Caption := IntToStr(Round(x.x+x.y+x.z)); // Anmerkung: Diese Zeile ist nur da,
// damit Delphi mir mein x nicht wegoptimiert ;-)
end;
Wird die Applikation mit F9 gestartet, und der Button1 gedrückt, so bleibt der Debugger an der Stelle begin (in der Funktion VectorSetValue) stehen.
Mit "Menü -> Ansicht -> Debug-Fenster -> CPU" kann man das CPU Fenster öffnen.
hier steht nun folgendes:
Code:
Unit1.pas.30: begin
0044D944 55 push ebp
0044D945 8BEC mov ebp,esp
Unit1.pas.31: Result.X := Value;
0044D947 8B5508 mov edx,[ebp+$08]
0044D94A 8910 mov [eax], edx
Unit1.pas.32: Result.Y := Value;
0044D94C 8B5508 mov edx,[ebp+$08]
0044D94F 895004 mov [eax + $04], edx
Unit1.pas.33: Result.Z := Value;
0044D952 8B5508 mov edx,[ebp+$08]
0044D955 895008 mov [eax + $08], edx
...
[ebp+$08] ist die Adresse von Value, also kann man auch mov edx, Value schreiben.
Da das Register edx durch ein mov [eax],edx nicht verändert wird braucht man es nicht noch mal mit der Adresse von Value zu laden.
Daraus ergibt sich Sakuras Quelltext:
Code:
mov edx, Value
mov [eax], edx
mov [eax + $04], edx
mov [eax + $08], edx
Wenn nun ein verändertes Array (z.B. Double als Typ) verwendet wird, kann man im CPU Fenster sehen, was Delphi daraus macht und sein
ASM entsprechend anpassen.