Autor Beitrag
KnuffelTom
Hält's aus hier
Beiträge: 5

Win XP SP2
Delphi 7 Enterprise
BeitragVerfasst: Fr 23.11.07 22:57 
Hi Leute,

versuche mich gerade an einem Formel- Parser, der auch Funktionen wie Min(a; B), Max(A, B) oder If(True; f(A); f(B)) bereitstellt. Als Basis dient mir die typarser- source von delfiphan, die absolut genial funktioniert, aber eben leider nicht über mathematische Funktionen hinaus geht.

Mein Problem ist, dass er für einzelnen Funktionen folgende arrays eingetragen hat:

ausblenden Delphi-Quelltext
1:
2:
fsqrt: array[0..1] of Byte = ($d9,$fa);
fsqr: array[0..3] of Byte = ($d9,$c0,$de,$c9);


Bei SQRT finde ich die Adresse sofort im CPU- Debug- Window. Probleme habe ich aber schon bei SQR. Ich komme nicht dahinter, wo delfiphan diese Adressen her hat (@delfiphan: Falls Du das hier liest... danke für Deine Hilfe per PN - wollte Dich blos nicht weiter direkt nerven! ;o)

Ich gebe allerdings zu, dass ich keine Ahnung vom CPU- Debug- Window und dessen Nutzung habe.

Danach kommen noch nettere Funktionen wie:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
fexp : array[0..21] of Byte =
   ($9,$ea,$de,$c9,$d9,$c0,$d9,$fc,$dc,$e9,$d9,$c9,$d9,$f0,$d9,$e8,$de,$c1,$d9,
    $fd,$dd,$d9);
 fheaviside: array[0..19] of Byte =
   ($d9,$ee,$d8,$d9,$9b,$df,$e0,$9e,$76,$06,$dd,$d8,$d9,$ee,$eb,$04,$dd,$d8,$d9,
    $e8);
 fround: array[0..12] of Byte =
   ($83,$ec,$08,$df,$3C,$24,$9b,$df,$2c,$24,$83,$c4,$08);
 farcsin: array[0..11] of Byte =
   ($d9,$c0,$d8,$c8,$d9,$e8,$de,$e1,$d9,$fa,$d9,$f3);
 farccos: array[0..13] of Byte =
   ($d9,$c0,$d8,$c8,$d9,$e8,$de,$e1,$d9,$fa,$d9,$c9,$d9,$f3);
 ftrunc: array[0..35] of Byte =
   ($83,$ec,$0c,$d9,$3c,$24,$d9,$7C,$24,$02,$66,$81,$4c,$24,$02,$00,$0f,$d9,$6c,
    $24,$02,$df,$7c,$24,$04,$9b,$d9,$2c,$24,$59,$df,$2c,$24,$83,$c4,$08);
 ffrac: array[0..34] of Byte =
   ($d9,$c0,$83,$ec,$04,$d9,$3c,$24,$d9,$7c,$24,02,$9b,$66,$81,$4c,$24,$02,$00,
    $0f,$d9,$6c,$24,$02,$d9,$fc,$9b,$d9,$2c,$24,$83,$c4,$04,$de,$e9);
 fsign: array[0..23] of Byte =
   ($d9,$ee,$d8,$d9,$9b,$df,$e0,$9e,$76,$08,$dd,$d8,$d9,$e8,$d9,$e0,$eb,$06,$73,
    $04,$dd,$d8,$d9,$e8);



Ich wollte eigentlich sowas ähnliches für Min, Max, Mod, usw. verwenden, aber wenn ich die Adressen nicht finde, kann ich auch delfiphans unit nicht erweitern.

Hoffentlich blickt wenigstens einer von Euch durch und erleuchtet mich.

Danke im Voraus,

der Knufflige.

p.s.: Ich hoffe auch, dass meine Frage hier an der richtigen Stelle steht. Falls nicht, tut's mir ehrlich leid.
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Sa 24.11.07 02:03 
In dem Array stehen jeweils die ASM-Opcodes für die BEfehle. Der Inhalt der Arrays wird also direkt ausgeführt.

_________________
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.
KnuffelTom Threadstarter
Hält's aus hier
Beiträge: 5

Win XP SP2
Delphi 7 Enterprise
BeitragVerfasst: Sa 24.11.07 15:24 
Titel: Aber woher?
Hallo BenBE,

danke für die frühmorgendliche und schnelle Antwort. Allerdings bin ich leider keinen Schritt weiter, als vorher.

Mir war schon klar, WAS da passiert und vermutlich wird das aus Performancegründen gemacht. Meine eigentliche Frage aber ist ja, wie und wo ich diese Adressen selber auslesen kann. Wie im vorigen Post beschrieben klappt das für SQRT ganz simpel, da im CPU- Debug- Window die Funktion "fsqrt" direkt drinsteht. Bei Funktionen wie Min, Max oder delfiphans "heavyside" ist das nicht mehr so einfach.

Daher bitte:

Wie geht man in einem solchen Fall vor?

Mein Codeansatz war:

ausblenden Delphi-Quelltext
1:
  MyVar := Min(1, 2);					


und dort einen Haltepunkt setzen. Nun das CPU- Debug- Window öffnen. Im Falle von SQRT direkt die Adresse rausschreiben.
Aber im diesem Falle (bei Funktion Min) tue ich nun Was????

In dem CPU- Fenster gibt's ja auch verschiedene Sektionen... irgendwo dort stehen bestimmt diese Adressen.

Vielen Dank für Eure Tips,

der Knufflige.
Allesquarks
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 510

Win XP Prof
Delphi 7 E
BeitragVerfasst: Sa 24.11.07 15:43 
Opcodes sind keine Adressen sondern erstmal Befehle, die manchmal eine Adresse enthalten. Wie man die baut dafür gibt es bestimmte regeln und Tabellen einfach mal nach opcode vlt noch befehlssatz googeln ansonsten in Büchern über assembler wird man häufig fündig. In Assembler gepackt ist hinten ein Abschnitt, der das Zusammensetzen erläutert.
Edit:
Vielmehr sind diese arrays sozusagen die von delfifan compilierten Funktionen fheavyside etc. Wenn du jetzt ein min haben möchtest musst du dies zunächst programmieren und dann in Opcodes schreiben
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: So 13.01.08 12:10 
Ist zwar schon älter, aber trotzdem:

Zunächst mal folgendes:
Zitat:
ausblenden Delphi-Quelltext
1:
2:
3:
fexp : array[0..21] of Byte =  
   ($d9,$ea,$de,$c9,$d9,$c0,$d9,$fc,$dc,$e9,$d9,$c9,$d9,$f0,$d9,$e8,$de,$c1,$d9,  
    $fd,$dd,$d9);

Dieses d ist auf mysteriöse Weise verschwunden :shock:. Das heisst die Funktion exp() hat noch nie funktioniert (e^x allerdings schon). ;)

Zur Frage:
tyParser unterstützt in den Ausdrücken nur eindimensionale Funktionen (also sin(x), cos(x), aber nicht min(x,y)). Sowas könnte der Compiler-Compiler, der ist allerdings recht langsam.

Trotzdem:
min/max wird zwar nicht direkt unterstützt, kann aber zusammengebastelt werden:
max(a,b) = heaviside(a-b)*(a-b)+b
min(a,b) = heaviside(a-b)*(b-a)+a
mod(a,b) = a-trunc(a/b)*b  (für a und b natürliche Zahlen)