Entwickler-Ecke

Algorithmen, Optimierung und Assembler - Mathemetische Berechnung zu Assembler


ScorpionKing - Di 05.04.05 19:56
Titel: Mathemetische Berechnung zu Assembler
Hi Leute,
ich habe folgendes Problem: Ich will eine Berechnung (extended, also mit komma) in Assembler rechnen.

Wie bekomme ich zum Beispiel 1/6*a+4/2 in einen Asm-Code?

MfG, ScorpionKing!


Moderiert von user profile iconChristian S.: Topic aus Off Topic verschoben am Di 05.04.2005 um 20:06


BenBE - Di 05.04.05 20:13
Titel: Re: Mathemetische Berechnung zu Assembler
user profile iconScorpionKing hat folgendes geschrieben:
Hi Leute,
ich habe folgendes Problem: Ich will eine Berechnung (extended, also mit komma) in Assembler rechnen.

Wie bekomme ich zum Beispiel 1/6*a+4/2 in einen Asm-Code?

MfG, ScorpionKing!


Eigentlich ganz einfach:
1. Umwandeln in RPN-Schreibweise:
Aus 1/6*a+4/2 wird 1 6 / a * 4 2 / +

2. Vereinfachen:

Quelltext
1:
2 6 a / +                    


3. Schreiben der FPU-Befehle:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
//2
    FILD WORD PTR [@@Data_Int2] //**

//6
    FILD WORD PTR [@@Data_Int6] //**

//a
    FLD TBYTE PTR [a] //*

//Division a / 6
    FDIVP //***

//Addition (a/6) + 2
    FADDP

//Skip the Data
    JMP @@SkipData

//Define the standard Data
@@Data_Int6:
    DW 6
@@Data_Int2: 
    DW 2

@@SkipData:


* TBYTE PTR kann entfallen, wenn Speichervariablen genutzt werden, bei Registern gibt es die Speichergröße und somit den Typ an. Für das Laden von Integern verwendet man FILD.
** Laden von Integern oder anderen Konstanten geht am einfachsten über DWord-Preallocations im Code-Segment. Für die Werte 0, 1 und Pi gibt es die Befehle FLDZ, FLD1 und FLDPI (sowie noch weitere Konstanten, die man häufiger braucht).
*** Bei FDIV und FSUB ist ST0 immer Zielregister. und der erste Operand. Die Reverse-Operationen vertauschen die Quelloperanden:
FDIV ST(0), ST(i) :arrow: ST(0) := ST(0) / ST(i)
FDIVR ST(0), ST(i) :arrow: ST(0) := ST(i) / ST(0)
Das P hinter dem Befehl sagt nur, dass der Zweite Operand vom Floating Point Stack entfernt werden soll.
Die Kurzformen FDIVP und FDIVRP haben die Impliziten Argumente ST(0), ST(1).

That's it ^^


tommie-lie - Di 05.04.05 20:27
Titel: Re: Mathemetische Berechnung zu Assembler
user profile iconBenBE hat folgendes geschrieben:
1. Umwandeln in RPN-Schreibweise:
Aus 1/6*a+4/2 wird 1 6 / a * 4 2 / +

2. Vereinfachen:

Quelltext
1:
2 6 a / +                    
Mit der umgekehrten polnischen Notation arbeite ich nicht täglich, aber steht da nicht 6/a+2 und müsste da nicht eigentlich a/6+2 stehen? :gruebel:


ScorpionKing - Di 05.04.05 20:27

und wie sieht das in delphi aus?


tommie-lie - Di 05.04.05 20:29

user profile iconScorpionKing hat folgendes geschrieben:
und wie sieht das in delphi aus?
So:

Delphi-Quelltext
1:
result := 1/6 *a + 4/2;                    


BenBE - Di 05.04.05 21:05
Titel: Re: Mathemetische Berechnung zu Assembler
user profile icontommie-lie hat folgendes geschrieben:
Mit der umgekehrten polnischen Notation arbeite ich nicht täglich, aber steht da nicht 6/a+2 und müsste da nicht eigentlich a/6+2 stehen? :gruebel:


Nein, da Du nach dem Stackprinzip arbeitest ...


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
6 / a + 2
---------
      +
6 / a   2
---------
      +
  /     2
6   a


Nun liest man den Baum top-->down, left-->right in pre-order:

Quelltext
1:
+ / 6 a 2                    


Und durch umkehren erhält man die RPN (post-order, bottom-->up):

Quelltext
1:
6 a / 2 +                    


Wenn man aber die Ausgangsgleichung noch etwas vereinfacht, kann man durch anwenden des Distributiv-Gesetzes die Argumente der Addition vertauschen und so alle Zahlen hintereinander bekommen:

Quelltext
1:
((2) (6 a) /) +                    


tommie-lie - Di 05.04.05 21:21
Titel: Re: Mathemetische Berechnung zu Assembler
user profile iconBenBE hat folgendes geschrieben:

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
6 / a + 2
---------
      +
6 / a   2
---------
      +
  /     2
6   a


Nun liest man den Baum top-->down, left-->right in pre-order:

Quelltext
1:
+ / 6 a 2                    


Und durch umkehren erhält man die RPN (post-order, bottom-->up):

Quelltext
1:
6 a / 2 +                    
Schon, aber ScorpionKings Term sah so aus:
ScorpionKing hat folgendes geschrieben:
1/6*a+4/2
Und von links nach rechts gelesen, da beides Punktrechnung ist, ist 1/6*a bei mir a/6 und nicht 6/a ;-)

Oder ist es schon zu spät für mich? :gruebel:


Aber danke für die Erklärung, jetzt muss ich mir RPN nicht jedesmal zu Fuß überlegen, sondern habe ein Schema für sowas, falls die Terme mal länger werden ;-)


Moritz M. - Di 05.04.05 21:22
Titel: Re: Mathemetische Berechnung zu Assembler
Nochmal kurze Frage an BenBE (Wohl die gleiche wie tommie-lie)

Wenn ich 1/6*a+4/2 vereinfache, komm ich auf a/6 + 2

In RPN wäre das doch 6 / 2 +, oder?
Wie kommst du auf 2 6 a / +?


tommie-lie - Di 05.04.05 21:32
Titel: Re: Mathemetische Berechnung zu Assembler
user profile iconMoritz M. hat folgendes geschrieben:
In RPN wäre das doch 6 / 2 +, oder?
Unvereinfacht ja.

Moritz M. hat folgendes geschrieben:
Wie kommst du auf 2 6 a / +?
Nein, das ist nicht meine Frage.
Vorrausgesetzt Bens Term stimmt, wäre 6 a / 2 + umgestellt (nicht vereinfacht im Sinne, daß es einfacher ist :mrgreen:) 2 6 a / +. Siehe Bens Anhängsel:
BenBE hat folgendes geschrieben:
Wenn man aber die Ausgangsgleichung noch etwas vereinfacht, kann man durch anwenden des Distributiv-Gesetzes die Argumente der Addition vertauschen und so alle Zahlen hintereinander bekommen:((2) (6 a) /) +
Vorraussetzung natürlich, der Parser beachtet die Regel "Punkt- vor Strich-Rechnung" kann man dann die Klammern weg lassen und man erhält Bens Term:
Ich schiebe 2 auf den Stack. Ich schiebe 6 auf den Stack. Ich schiebe a auf den Stack. Ich dividiere die obersten beiden Elemente des Stacks (und hier liegt bei mir die Verwirrung, ich Teile 6/a, dabei ist 1/6*a aber a/6) und schiebe das Ergebnis wieder auf den Stack. Dann addiere ich die obersten beiden Elemente des Stacks (2 und das Ergebnis der Division). Fertig.


delfiphan - Di 05.04.05 22:09

Siehe mein Parser / Runtime Compiler für mathematische Ausdrücke [http://www.delphi-forum.de/viewtopic.php?p=227715#227715]. Der compiliert einen String mit einer Formel in eine asm-Funktion.


ScorpionKing - Mi 06.04.05 12:34

user profile icondelfiphan hat folgendes geschrieben:
Siehe mein Parser / Runtime Compiler für mathematische Ausdrücke [http://www.delphi-forum.de/viewtopic.php?p=227715#227715]. Der compiliert einen String mit einer Formel in eine asm-Funktion.


ja, den schau ich mir mal an! danke!

MfG, Scorpion!