Autor |
Beitrag |
Allesquarks
      
Beiträge: 510
Win XP Prof
Delphi 7 E
|
Verfasst: Di 20.09.05 00:50
Habe versucht strtofloat unter assembler aufzurufen. Hierfür müsste ich ja eigentlich einen Zeiger auf den String nach eax laden. Da dieser String (realvalue) Bestandteil einer Klasse (nummer1,result) ist lade ich diesen Zeiger über einen weiteren Zeiger (zweimal).
Delphi-Quelltext 1: 2: 3: 4: 5:
| asm mov eax,nummer1; mov eax,[eax+offset nummer1.realvalue+$4]; call strtofloat; end; |
Das funktioniert so weit so gut.
Nun wollte ich noch eine extended aus der FPU so wie sie ist in diesen String speichern. Hatte damit immense Probleme und habe beim Compiler abgekupfert der vor dem Eingriff in einen String immer uniquestring aufruft. Diese Funktion sollte nun doch eigentlich auch einen Zeiger auf den String in eax erwarten. Seltsamerweise führt eine analoge Schreibweise zu obigem Beispiel nicht zum Erfolg, sondern diesmal addiert der Compiler nur den zum Klassenanfang relativen Offset wo ich dachte dass dann der Zeiger auf den String steht zu eben dem Klassenanfang.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| asm fadd st(0),st(1); mov eax,result; add eax,offset result.realvalue+$4; call uniquestring; fstp tbyte ptr [eax]; fstp st(0); end; |
Meiner Meinung nach wird dadurch der Zeiger auf den String gar nicht geladen??
Jedenfalls wollte ich nicht mit dem Kopf durch die Wand und dachte ich könnte diese Inkonsistenz ertragen (oder liege ich da falsch). Er hat bei der Ausführung damit keine Probleme jedoch wird nach Ausführung bei Beenden der Form nun jedesmal eine EInvalidPointer-Exception ausgelöst.
Wäre für Hilfe sehr dankbar!
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Di 20.09.05 12:47
Zeile 5 und 6 in deinem zweiten Beispiel können schon hinten und vorne nicht funktionieren.
Delphi-Quelltext 1: 2: 3: 4:
| asm CALL UniqueString FSTP TBYTE PTR [EAX] end; |
ruft UniqueString auf, die in EAX den Zeiger auf das erste Zeichen eines Strings zurückgibt.
Irgendwie haut dein Source hinten und vorne nicht hin. Kannst Du bitte mal die Pascal-Version von dem (mit Deklarationen) geben, von dem, was Du machen willst? Dann lässt sich das einfacher in ASM umsetzen.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
Allesquarks 
      
Beiträge: 510
Win XP Prof
Delphi 7 E
|
Verfasst: Di 20.09.05 13:21
Davon gibts praktisch keine Pascal Version. Schreibe an einem Rechner und wollte mir das ständige rumkonvertieren sparen und deshalb ein abstrahiertes Datenformat TNumber schreiben, in dem je nach Nützlichkeit int,extended, aber auch vom Benutzer eingegebene mathematische Phrasen usw. stehen können. Und weil diese unterschiedlich lang sind wollte ich string eigentlich nur als Speicherstelle variabler Länge benutzen um die Bequemlichkeiten der Stringverwaltung zu nutzen. Extended direkt innen String zu schreiben hat mir Delphi natürlich nicht erlaubt. Habe dann versucht über Zeiger die Typenprüfung zu umgehen funktionierte aber nicht. Also wollte ich das mit assembler machen. Einfach bei der Adresse des Strings in diesen schreiben (da gab es immer eine Zugriffsverletzung) und da delphi immer uniquestreing aufruft habe ich das genauso gemacht. Eine genaue Beschreibung der Funktion habe ich bisher leider nicht gefunden.
Delphi-Quelltext 1: 2: 3: 4: 5: 6:
| TNumber = class(TVector) realvalue:string; imaginaryvalue:string; realtag:byte; imaginarytag:byte; end; |
In der vorherigen Version als TNumber keine Klasse sondern Variable war, hat es auch einwandfrei funktioniert (natürlich immer nur über eine Zeigerstufe).
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Di 20.09.05 13:34
Wieso geht das mit dem Extended direkt in String schreiben nicht?
Funzt doch:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| var E: PExtended; S: String; begin S := '0123456789'; E := @S[1]; E^:= 1.5; end; |
Aber Recht hat Delphi schon. Sowas perverses darf man nicht zulassen ^^
Achso, wegen der ASM-Umsetzung, würd ich die Verwendung von PChar präferenzieren. Die lassen sich mit ASM um einiges besser als Strings verwalten (über simple GetMem\ReallocMem und FreeMem. Bei Strings hast Du zahlreiche private Funktionsaufrufe der System-Unit drin (weil vieles Compiler Magic ist). Kann ich Dir nicht empfehlen, auch wenn ich erst neulich hier im Forum geschrieben hab, wie das für Raise Exxception.Create('TestException'); funktioniert.
Weiterhin ein Tipp:
Delphi-Quelltext 1: 2: 3: 4:
| asm MOV EAX, DWORD PTR [S] LEA EAX, DWORD PTR [S] end; |
Das obere Beispiel müsste dann etwa so hier lauten:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| var S: String; asm MOV EAX, 32 MOV EDX, 10 CALL StringOfChar MOV DWORD PTR [S], EAX FLDPI FSTP TBYTE PTR [EAX] end; |
Ungetestet. Siehe CPU-Fenster beim ersten Beispiel.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
Allesquarks 
      
Beiträge: 510
Win XP Prof
Delphi 7 E
|
Verfasst: Di 20.09.05 13:45
Herzlichen Dank erstmal. Was meinst du mit Zitat: | mov eax,32;//Leerzeichen |
?
|
|
uall@ogc
      
Beiträge: 1826
Erhaltene Danke: 11
Win 2000 & VMware
Delphi 3 Prof, Delphi 7 Prof
|
Verfasst: Di 20.09.05 13:49
32 ist der ASCII wert für nen Leerzeichen
_________________ wer andern eine grube gräbt hat ein grubengrabgerät
- oder einfach zu viel zeit
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Di 20.09.05 13:49
Damit setze ich die Parameter für function StringOfChar(C:Char; Len: Integer): String; register;, die in EAX (Paramter 1) das Zeichen (Leerzeichen hat ASCII-Code 32) und in EDX die Anzahl der Zeichen (in dem Fall für Extended 10) haben möchte.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
Allesquarks 
      
Beiträge: 510
Win XP Prof
Delphi 7 E
|
Verfasst: Di 20.09.05 13:58
Danke schön noch einmal! Werde versuchen das mit den Pchar's zu machen. Dennoch ist mir durch diesem Thread die Bedeutung ddes Uniquestring völlig abhanden gekommen?!? Aber das brauche ich ja dann wenigstens nicht mehr!
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Di 20.09.05 16:20
UniqueString ist eine Funktion der Delphi-RTL, die dafür sorgt, dass man einen String referenziert, auf den es nur eine Referenz gibt.
Das braucht man dazu, um bei Delphi-Strings, auf die es mehrere Referenzen gibt, eindeutig zu machen. Z.B.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7:
| var A,B,C: String; begin A := 'Test'; B := A; C := B; end; |
enthalten A,B UND C in diesem Beispiel die Referenz auf den gleichen String, der intern weiß "auf mich gibt's 3 Referenzen".
Wenn Du nun C := UniqueString(B); machen würdest, enthält C zwar den gleichen Text wie B, zeigt aber auf einen völlig anderen String.
Dies wird z.B. wichtig, wenn Du C bearbeiten würdest. Angenommen, du änderst in C ein Zeichen, wenn C=B=A auf den gleichen String zeigen.
C[3] := 'x'; würde dann nicht nur den String C, sondern auch A und B ändern.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
Allesquarks 
      
Beiträge: 510
Win XP Prof
Delphi 7 E
|
Verfasst: Di 20.09.05 17:07
Gut dann hatte ich das eigentlich doch richtig verstanden aber wieso soll sie denn dann einen Zeiger auf die erste Position zurückliefern. Bzw. wieso musste ich sie immer aufrufen (auch wenn ich keine Instanzen des String erzeugt hatte). Nebenbei: Muss ich wenn ich PChar's verwende nicht auch eine äquivalente Funktion aufrufen?
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Di 20.09.05 17:22
Jain. Für PChars musst Du Dich selber um die Referenz-Zählung (braucht man nicht) und Speicherverwaltung kümmern. Da Du dafür aber keinerlei Funktionen der System-Unit von Delphi (außer den offiziellen Speichermanager-Funktionen) brauchst, ist das mit ASM recht easy.
Eine Funktion wie UniqueString brauchst Du bei PChar nicht, weil Du selber entscheidest, wann eine Kopie erzeugt wird.
Und wegen Pointer auf erstes Zeichen:
Delphi-Quelltext 1: 2: 3: 4: 5:
| String = packed record Offset -8 RefCounter: DWORD; Offset -4 Length: DWORD; Offset 0 Data: Array [DWORD] of Char; end; |
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
|