Auf dieser Seite wird ein erweitertes Übungsbeispiel für den Umgang mit den FPU-Stackregistern erarbeitet. Ausgangspunkt ist die Ermittlung der Windungsanzahl einer einlagigen Zylinderspule für einen Schwingkreis für die Hochfrequenztechnik. Der technische Hintergrund steht in „Das Spulennomogramm”. Auf der gleichen Seite findet sich ein entsprechendes BASIC-Programm mit den mathematischen Formeln:
m = s + d / 2 f = (d / 2) ^ 2 * 3.14 w = SQR((l * 1000 * m) / (4 * 3.14 * f)) In der üblichen Infix-Schreibweise enthalten die verwendete mathematische Formeln Klammern, Bruchstriche und das Wurzelzeichen. Damit wird die Reihenfolge des Rechenvorgangs bestimmt. In der Assemblervariante hat man diese elegante Möglichkeit zur Bestimmung der Reihenfolge nicht. Hier muss der Programmierer die Reihenfolge der einzelnen Rechenschritte im Programmablauf festlegen: Er fungiert quasi als „Preprozessor”. Die FPU-StackregisterDer mathematische Coprozessor (FPU) verwendet für Gleitkommazahlen acht Register die als Kellerspeicher (Stack) organisiert sind. Sie heißen st(0) bis st(7). Alternativ kann das oberste Stackregister st(0) als st angesprochen werden.Werte werden in das oberste FPU-Stackregister durch Befehle wie fld, fild und fbld eingetragen. Werte aus dem obersten FPU-Stackregister lassen sich mit Befehlen wie fst, fstp, fist, fistp und fbstp auslesen. Die Befehle, die auf stp enden räumen dabei den Wert vom Stack ab. Die Befehle mit st am Ende speichern den Wert im Hauptspeicher ohne ihn vom Stack zu entfernen. Die FPU speichert ihre Daten in ihren Registern immer im 80 bit langen Gleitkommaformat (Real). Beim Rechnen nutzt die FPU grundsätzlich mindestens 19 Dezimalstellen. Eine Besonderheit stellt die Verwendung der Zahlendarstellung im „Packed Decimal-Formats” dar. Es handelt sich um eine Sonderform der Darstellung als „Binary Coded Decimal” (BCD). Dabei werden in jedem Halbbyte nur die binären Darstellungen der Ziffern von 0 bis 9 genutzt. Bei der FPU verwendet das Packed Decimal-Format 10 Bytes zur Darstellung von 18 Ziffern. Die so dargestellte Zahl ist immer ein Ganzzahl (Integer). Das höchste Bit des höchsten Bytes (Byte 19) ist das Vorzeichenbit: Ist es gesetzt, ist die Zahl negativ. Ist es nicht gesetzt, ist die Zahl positiv. Die übrigen 7 bits von Byte 19 werden ignoriert. Die hexadezimale Darstellung der Zahl -65536 im „Packed Decimal-Formats” ist:
Da bei Intel Daten im „little–endian-Format” gespeichert werden, würde dies im Speicherdump so aussehen:
Im Datenbereich des Speichers werden Zahlen des Packed Decimal-Formates mit dem Schlüsselwort tbyte deklariert. Genau zwei Befehle beschäftigen sich mit der Übertragung von Daten zwischen dem Datenbereich des Hauptspeichers und dem obersten FPU-Stackregister:
Für Details sei auf die beiden Befehlsbeschreibungen in →SIMPLY FPU by Raymond Filiatreault verwiesen. |
Bei dem folgenden Programm handelt es sich um ein Übungsprogramm. Somit fehlt die Eingabe der in die Berechnung eingehenden Daten per Tastatur. Wie dies im Prinzip gemacht wird, geht aus dieser vorhergehenden Webseite hervor.
; Beispiel Berechnung einer einlagigen Zylinderspule ; Siehe dazu das BASIC-Programm auf: https://fredriks.de/dl8wa/d2.php?f=2 ; ; moegliche Eingabedaten: ; l = Induktivität in uH ; d = Spulendurchmesser in cm ; s = Spulenlänge in cm ; Zwischenwerte: ; r = Radius der Spule aus d/2 ; m = s + r ; f = r ^ 2 * 3.14 ; Ergebnis Windungszahl ; w = SQR((l * 1000 * m) / (4 * 3.14 * f)) ; bzw. gekuerzt auf ; w = SQR((l * 250 * m) / (3.14 * f)) ; ------------------------------------------- .486 .model flat, stdcall option casemap:none ; case sensitive ; ------------------------------------------- .XLIST include \masm32\include\windows.inc include \masm32\macros\macros.asm ; MASM support macros include \masm32\include\user32.inc include \masm32\include\masm32.inc include \masm32\include\kernel32.inc include \masm32\include\Fpu.inc include \masm32\include\msvcrt.inc includelib \masm32\lib\user32.lib includelib \masm32\lib\masm32.lib includelib \masm32\lib\kernel32.lib includelib \masm32\lib\Fpu.lib includelib \masm32\lib\msvcrt.lib .LIST ; ------------------------------------------- .data w dt 0 ;Windungszahl l dt 0 ;Induktivität in uH d dt 0 ;Spulendurchmesser in cm s dt 0 ;Spulenlaenge in cm ;Eingabedaten l_inp db "0.21",0 d_inp db "1",0 s_inp db "1",0 m dt 0 ;Zwischenergebnis f dt 0 ;Zwischenergebnis r dt 0 ;Spulenradius in cm ;Zur Anzeige w_txt db "Windungsanzahl: " w_zahl db 34 dup(0) l_txt db 13,10,"Induktivitaet (uH): " l_zahl db 34 dup(0) d_txt db 13,10,"Spulendurchmesser (cm): " d_zahl db 34 dup(0) s_txt db 13,10,"Spulenlaenge (cm): " s_zahl db 34 dup(0) MsgBoxCaption db "Spulendaten",0 .code start: ;konvertiere d_inp in REAL10 und speichere es in der FPU invoke FpuAtoFL, ADDR d_inp, 0, DEST_FPU ;errechne Radius und speichere ihn in r invoke FpuDiv, 0, 2, ADDR r, SRC1_FPU or SRC2_DIMM or DEST_MEM ;konvertiere s_inp in REAL10 und speichere sie in der FPU invoke FpuAtoFL, ADDR s_inp, 0, DEST_FPU ;errechnet m = s + r und speichere m invoke FpuAdd, 0, ADDR r, ADDR m, SRC1_FPU or SRC2_REAL or DEST_MEM ;errechnet f = r ^ 2 * 3.14 und speichere in f invoke FpuMul, ADDR r, ADDR r, 0, SRC1_REAL or SRC2_REAL or DEST_FPU invoke FpuMul, 0, FPU_PI, ADDR f, SRC1_FPU or SRC2_CONST or DEST_MEM ;Ermittlung der Windungsanzahl bei vorgegebenen Induktivitaet ;errechne phi * f und speichere Produkt in f invoke FpuMul, FPU_PI, ADDR f, ADDR f, SRC1_CONST or SRC2_REAL or DEST_MEM ;errechne l * 250 * m und speichere Produkt in FPU invoke FpuAtoFL, ADDR l_inp, 0, DEST_FPU invoke FpuMul, 0, 250, 0, SRC1_FPU or SRC2_DIMM or DEST_FPU invoke FpuMul, 0, ADDR m, 0, SRC1_FPU or SRC2_REAL or DEST_FPU ;Division, dann Wurzel ziehen invoke FpuDiv, 0, ADDR f, 0, SRC1_FPU or SRC2_REAL or DEST_FPU invoke FpuSqrt, 0, 0, SRC1_FPU or DEST_FPU ;konvertiere windungsanzahl in ASCII mit 2 nachkommstellen invoke FpuFLtoA, 0, 2, ADDR w_zahl, SRC1_FPU or SRC2_DIMM or DEST_MEM ;Ausgabe der Spulendaten. l, d und s werden aus den Eingabedaten uebernommen ;szCopy quelle ziel invoke szCopy, ADDR l_inp, ADDR l_zahl invoke szCopy, ADDR d_inp, ADDR d_zahl invoke szCopy, ADDR s_inp, ADDR s_zahl invoke szCatStr, ADDR w_txt, ADDR l_txt invoke szCatStr, ADDR w_txt, ADDR d_txt invoke szCatStr, ADDR w_txt, ADDR s_txt invoke MessageBox, 0, ADDR w_txt, ADDR MsgBoxCaption, MB_OK invoke ExitProcess, 0 end start ![]() Berechnet wurde lediglich die Anzahl der Windungen. |
Bemerkungen zum ProgrammDas Programm besteht fast ausschließlich aus Aufrufen der beim MASM32-SDK mitgelieferten FPU-Funktionen. Sie erleichtern die Programmierung der FPU. Allerdings müssen sie die beim Aufruf übergebenen Parameter auswerten. Deshalb benötigen sie mehr Rechenzeit als die individuelle Nutzung der entsprechenden FPU-Befehle.→SIMPLY FPU by Raymond Filiatreault ist eine sehr gut verständliche Beschreibung der FPU-Programmierung. Der Text ist in amerikanischem Englisch. |