Sinus-Berechnung

Diskussion zum Thema Programmierung unter DOS (Intel x86)
Antworten
TomCat
MemMaker-Benutzer
Beiträge: 87
Registriert: Do 1. Dez 2011, 17:16

Sinus-Berechnung

Beitrag von TomCat »

Hallo,

habe mit dem Co-Prozessor noch nicht viel gemacht.
Nur mal die Quadrat-Wurzel berechnet. also mit:
fild das Quadword geladen. dann
fsqrt aufgerufen
und das Ergebnis mit:
fistp in ein Double-Word geladen

es geht mir darum jetzt den Sinus, bzw. die trigonometrischen Funktionen mittels Co-Prozessor zu erhalten.
Weiß jemand wie das geht?

Danke schon mal im Voraus,
TomCat
freecrac
DOS-Guru
Beiträge: 861
Registriert: Mi 21. Apr 2010, 11:44
Wohnort: Hamburg Horn

Re: Sinus-Berechnung

Beitrag von freecrac »

TomCat hat geschrieben:Hallo,

habe mit dem Co-Prozessor noch nicht viel gemacht.
Nur mal die Quadrat-Wurzel berechnet. also mit:
fild das Quadword geladen. dann
fsqrt aufgerufen
und das Ergebnis mit:
fistp in ein Double-Word geladen

es geht mir darum jetzt den Sinus, bzw. die trigonometrischen Funktionen mittels Co-Prozessor zu erhalten.
Weiß jemand wie das geht?

Danke schon mal im Voraus,
TomCat
Weil die FPU nicht so schnell arbeitet empfielt es sich nach Möglickeit stattdessen Integer-Befehlen der CPU zu verwenden. Die Vorarbeit dazu kann aber die FPU für uns erledigen.

(Ich bin aber nicht so gut darin mathematische Aufgaben zu lösen und tue mich damit selber schwer.)

Mit der folgenden Routine wird eine Sinus/Cosinus-Tabelle mit Integerwerten erstellt und gespeichert.
Diese Tabelle kann dann später von einem anderen Programm geladen und verwendet werden.

Code: Alles auswählen

.MODEL SMALL
.386P
.387
          Scale   = 4
          Grad    = 360 * Scale
          Endtab  = 450 * Scale
          Foktor  = 10000h

  CODE SEGMENT use16 'CODE'
 assume cs:CODE,ds:DATEN,ss:STAPEL
;---------------------------------------------------------------------------
 org 100h
START:    mov     ax, DATEN
          mov     ds, ax
          finit
          call TABLE
          mov     dx, OFFSET TABNAM
          call MAKDAT
          xor     dx, dx
          mov     cx, Endtab*4
          call WRITE
          call CLOSE
;---------------------------------------------------------------------------
          xor     al, al              ; kein Fehler
DOS:      mov     ah, 4Ch             ; Dos-Rücksprung, Programm-Ende
          int   21h
;────────────────────────────────────────────────────────────────────────────
;                      U N T E R - R O U T I N E N
;────────────────────────────────────────────────────────────────────────────
 org START + ((($-START)/16)*16)+16
;─────────────────────────────────────────────────────────────────────────────
;                          S i n u s - T a b e l l e
;─────────────────────────────────────────────────────────────────────────────
TABLE:    xor     di, di              ; Sinus-Tabelle anlegen
;-------------------------------------
TAB:      fldpi                       ; PI laden
          fimul  DWORD PTR[I]         ; Zaehler mal PI
          fidiv  DWORD PTR[TEIL]      ; durch 180(INT) teilen
          fsin                        ; davon den Sinus
          fimul  DWORD PTR[FAKT]
          fistp  DWORD PTR[di]        ; in die Sinus-Tabelle schreiben
;-------------------------------------
          inc    WORD PTR[I]          ; Grad-Zähler erhöhen
          add     di, 4               ; Tabellen-Index erhöhen
          cmp    WORD PTR[I], Endtab  ;  Tabellen-Ende erreicht ?
          jnz TAB
          ret
;─────────────────────────────────────────────────────────────────────────────
 org START + ((($-START)/16)*16)+16
;----------------------------------------------------------------------------              
MAKDAT:   mov     ah, 3Ch             ;  Datei erstellen  (ah=3C/5B)
          xor     cx, cx 
          int  21h
          mov     bx, ax
          ret
;─────────────────────────────────────────────────────────────────────────────
 org START + ((($-START)/16)*16)+16
;----------------------------------------------------------------------------
WRITE:    mov     ah, 40h             ;  Datei beschreiben
          int   21h
          ret
;─────────────────────────────────────────────────────────────────────────────
 org START + ((($-START)/16)*16)+16
;----------------------------------------------------------------------------              
CLOSE:    mov     ah, 3Eh             ;  Datei schließen
          int   21h
          ret
;---------------------------------------------------------------------------
  CODE ends
;────────────────────────────────────────────────────────────────────────────
;                       D A T E N - B E R E I C H
;────────────────────────────────────────────────────────────────────────────
  DATEN SEGMENT use32 'DATA'
 org 0
;---------------------------------------------------------------------------
SINTAB DB Endtab DUP (?,?,?,?)
;-------------------------------------
TEIL   DW Grad/2, ?
I      DW 0, 0
;-------------------------------------
FAKT   DD Foktor
;-------------------------------------
TABNAM DB "Sin2Int.tab", 0
  DATEN ends
;────────────────────────────────────────────────────────────────────────────
  STAPEL SEGMENT use16 STACK 'STACK'
       DB 10h dup (?)
  STAPEL ends
;────────────────────────────────────────────────────────────────────────────
 end
Im nachfolgendem Listing wird ein Fraktalbild mit der FPU berechnet.

Code: Alles auswählen

.MODEL SMALL
.386
.387
;────────────────────────────────────────────────────────────────────────────
       Col       = 0C0h
       Iter      = 456
       Xstart    = 0
       Ystart    = 1699
;────────────────────────────────────────────────────────────────────────────
       Tast_Port =  60h               ; Port-Adresse des Tastatur-Controllers
       RGB_Write = 3C8h               ; Port-Adresse der Farb-Anteile (write)
;────────────────────────────────────────────────────────────────────────────
  CODE SEGMENT use16 'CODE'
 assume cs:CODE,ds:DATEN,ss:STAPEL
 org 100h
;────────────────────────────────────────────────────────────────────────────
START:    mov      ax, 13h            ;  320 x 200 x 256
	  int    10h
;-------------------------------------
	  mov      ax, DATEN
	  mov      ds, ax
	  mov      ax, 0A000h
	  mov      es, ax
;-------------------------------------
	  xor      al, al
	  mov      dx, RGB_Write
	  mov      si, OFFSET DAC     ; Quelle
	  mov      cx, 0FFh*3
	  out      dx, al             ; Farb-Nr. zur VGA-Karte
	  inc      dx                 ; VGA-PORT der Farb-Anteile     (data)
	  rep outsb                   ; Farb-Anteile zur Grafik-Karte
;-------------------------------------
	  finit                       ; FPU initialisieren
	  mov     DWORD PTR[Z], 100000
	  mov     DWORD PTR[A], 76541
	  fild     A
	  fidiv    Z
	  fchs
	  fst      A                  ; -.76548

	  mov     DWORD PTR[B], 76529
	  fild     B
	  fidiv    Z
	  fchs 
	  fst      B                  ; -.76528

	  mov     DWORD PTR[C], 9986
	  fild     C
	  fidiv    Z
	  fst      C                  ; .0997

	  mov     DWORD PTR[D], 9990
	  fild     D
	  fidiv    Z
	  fst      D                  ; .1003
;-------------------------------------
	  fild     NEUN
	  fidiv    ZEHN
	  fstp     PNEUN              ; 0.9
;-------------------------------------
	  fld      D
	  fsub     C
	  fidiv    YMAX
	  fstp     G                  ; G = (D-C)/YMAX

	  fld      B
	  fsub     A
	  fidiv    XMAX
	  fstp     F                  ; F = (B-A)/XMAX

	  mov     WORD PTR[X1], Xstart
	  mov     WORD PTR[Y1], Ystart
;---------------------------------------------------------------------------
       DB  0EAh                       ; Prefetch-Puffer löschen:
       DW  (OFFSET BEGINN)            ; Die folgenden Zeilen erzeugen
       DW  SEG CODE                   ; das Kommando JMP FAR CS:BEGINN
;---------------------------------------------------------------------------
 org START + ((($-START)/16)*16)+16   ; Code-Ausrichtung
;---------------------------------------------------------------------------
BEGINN:   mov     WORD PTR[X], 0

WW1:      call FRAK
	  inc     WORD PTR[X]
	  inc     WORD PTR[X1]
	  cmp     WORD PTR[X], 140h
	  jnz WW1

	  sbb     WORD PTR[X1], 140h
	  inc     WORD PTR[Y1]
;-------------------------------------
	  lds      si, DWORD PTR[COSEG] ; 320 * 200 = 64000   letzte Zeile
	  xor      di, di             ;                  vorletzte Zeile
	  mov      cx, 15920           ; Anzahl Zeilen die gescrollt werden
	  rep movsd
	  mov      ax, DATEN
	  mov      ds, ax
;-------------------------------------
	  in       al, Tast_Port      ; Tasten-Code holen
	  dec      al                 ;  Escape-Taste gedrückt ?
	  jnz BEGINN
;-------------------------------------
	  mov      ax, 3              ; Text-Mode
	  int    10h
;-------------------------------------
	  mov      ah, 1              ; Tastatur-Puffer löschen
	  int    16h
;-------------------------------------
	  xor      al, al             ; kein Fehler
DOS:      mov      ah, 4Ch            ; Dos-Rücksprung, Programm-Ende
	  int    21h
;────────────────────────────────────────────────────────────────────────────
;                      U N T E R - R O U T I N E N
;────────────────────────────────────────────────────────────────────────────
 org START + ((($-START)/16)*16)+16   ; Code-Ausrichtung
;---------------------------------------------------------------------------
FRAK:     fld      G
	  mov      dx, 1
	  fimul    Y1
	  fadd     C
	  fst      st(1)              ; K = G * Y + C
	  fstp     st(2)              ; J = K

	  fld      F
	  fimul    X1
	  fadd     A
	  fst      st(3)              ; I = F * X + A
	  fstp     st(4)              ; H = I

	  fld      st(2-1)
	  fmul     st, st(2)
	  fstp     st(5)              ; L = J * J

	  fld      st(4-1)
	  fmul     st, st(4)
	  fstp     st(6)              ; M = H * H

FRAK1:    cmp      dx, Iter           ; Iteration
	  ja  short FRAK2

	  fild     ZWEI
	  fmul     st, st(4)
	  fmul     st, st(2)
	  fadd     st, st(1)
	  fstp     st(2)              ; J = 2 * H * J + K

	  fld      st(6-1)
	  fsub     st, st(5)
	  fadd     st, st(3)
	  fstp     st(4)              ; H = M - L + I

	  fld      st(2-1)
	  fmul     st, st(2)
	  fstp     st(5)              ; L = J * J

	  fld      st(4-1)
	  fmul     st, st(4)
	  fst      st(6)              ; M = H * H

	  fadd     st, st(5)          ; M + L
	  fadd     PNEUN
	  fistp    WW

	  inc      dx
	  cmp     WORD PTR[WW], 5
	  jb  FRAK1

FRAK2:    add      dx, Col
	  mov      bx, 199
	  mov      di, bx             ; 320 Pixel a Zeile
	  shl      bx, 8
	  shl      di, 6
	  add      bx, di
	  add      bx, X              ; Y + X
	  mov     BYTE PTR es:[bx], dl ; Farb-Byte schreiben 0-255
	  ret
;---------------------------------------------------------------------------
  CODE ends
;────────────────────────────────────────────────────────────────────────────
;                       D A T E N - B E R E I C H
;────────────────────────────────────────────────────────────────────────────
  DATEN SEGMENT use32 'DATA'
 org 0
;---------------------------------------------------------------------------
A      DD ?
B      DD ?
C      DD ?
D      DD ?
F      DD ?
G      DD ?
Z      DD ?

X      DW ?, ?
Y      DW ?, ?
X1     DW ?, ?
Y1     DW ?, ?

XMAX   DW 320, ?
YMAX   DW 200, ?

ZWEI   DD 2
NEUN   DD 9
ZEHN   DD 10
PNEUN  DD ?     ; 0.9
WW     DW ?, ?

COSEG  DW 140h, 0A000h

;         rot  grün blau

DAC    DB 000h,000h,000h ;    0   rot
       DB 001h,000h,000h ;    1
       DB 002h,000h,000h ;    2

      ..... gekürzt... im Original werden alle Farbanteile aufgeführt...

       DB 0FDh,07Dh,000h ;    3
       DB 0FEh,07Eh,000h ;    4
       DB 0FFh,07Fh,000h ;    5
;---------------------------------------------------------------------------
  DATEN ends
;────────────────────────────────────────────────────────────────────────────
  STAPEL SEGMENT use16 STACK 'STACK'
;---------------------------------------------------------------------------
       DB 10h dup (?)
;---------------------------------------------------------------------------
  STAPEL ends
;────────────────────────────────────────────────────────────────────────────
 end
Dirk
TomCat
MemMaker-Benutzer
Beiträge: 87
Registriert: Do 1. Dez 2011, 17:16

Re: Sinus-Berechnung

Beitrag von TomCat »

Danke funktioniert perfekt !!

Leider fehlen mir die Arcus-Funktionen also Arcus Sinus z.b.
Da scheint es seltsamerweise keinen Co-Prozessor-Befehl zu geben oder täusche ich mich da?

Wie kann man das berechnen?
freecrac
DOS-Guru
Beiträge: 861
Registriert: Mi 21. Apr 2010, 11:44
Wohnort: Hamburg Horn

Re: Sinus-Berechnung

Beitrag von freecrac »

TomCat hat geschrieben:Danke funktioniert perfekt !!

Leider fehlen mir die Arcus-Funktionen also Arcus Sinus z.b.
Da scheint es seltsamerweise keinen Co-Prozessor-Befehl zu geben oder täusche ich mich da?

Wie kann man das berechnen?
Das musss man sich wohl selber ausrechnen lassen.

Mit folgenden Wörtern "fpu calculate arccos-function" gesucht und gefunden:
Art of Assembly von Randall Hyde
14.5 Sample Program: Additional Trigonometric Functions_
https://courses.engr.illinois.edu/ece39 ... H14-6.html

Dirk
TomCat
MemMaker-Benutzer
Beiträge: 87
Registriert: Do 1. Dez 2011, 17:16

Re: Sinus-Berechnung

Beitrag von TomCat »

asin proc near
fld st(0) ;Duplicate X on tos.
fmul ;Compute X**2.
fld st(0) ;Duplicate X**2 on tos.
fld1 ;Compute 1-X**2.
fsubr
fdiv ;Compute X**2/(1-X**2).
fsqrt ;Compute sqrt(x**2/(1-X**2)).
fld1 ;To compute full arctangent.
fpatan ;Compute atan of the above.
ret
asin endp

brauche die obige Funktion als integer Übergabe und Integer- Resultat damit ich das in einer Integer-Tabelle speichern kann.

Bekomme das nicht hin. Kann mir da einer dabei helfen?
freecrac
DOS-Guru
Beiträge: 861
Registriert: Mi 21. Apr 2010, 11:44
Wohnort: Hamburg Horn

Re: Sinus-Berechnung

Beitrag von freecrac »

TomCat hat geschrieben:asin proc near
fld st(0) ;Duplicate X on tos.
fmul ;Compute X**2.
fld st(0) ;Duplicate X**2 on tos.
fld1 ;Compute 1-X**2.
fsubr
fdiv ;Compute X**2/(1-X**2).
fsqrt ;Compute sqrt(x**2/(1-X**2)).
fld1 ;To compute full arctangent.
fpatan ;Compute atan of the above.
ret
asin endp

brauche die obige Funktion als integer Übergabe und Integer- Resultat damit ich das in einer Integer-Tabelle speichern kann.

Bekomme das nicht hin. Kann mir da einer dabei helfen?
Um Integer-Werte zu bekommen kann man sich das Ergebniss als Integerwert ausgeben lassen. Integer-Befehle sind am "i" im Befehl erkennbar. Mit "fist DWORD PTR[ADRESSE]" wird der Wert als Integerwert in den Speicher geschrieben.
Das macht natürlich nur dann Sinn, wenn der Wert nicht kleiner als 1.0 gross ist. Solche Werte muss man sonst vorher multiplizieren, damit die Nach-Kommastellen vor dem Komma verschoben werden.

Bei der Berechnung selber kann ich dir aber nicht weiter helfen, weil dafür müsste ich es vorher erst selber lernen solche Berechnungen zu verstehen.

...

Wichtig ist es auch darauf ausfzupassen, dass der FPU-Stack nicht überläuft und nicht nur Werte auf den FPU-Stack raufgeschoben werden, sondern die Werte auch wieder vom Stack gepopt werden. Dafür kann man z.B. ein "p" hinter dem "fist-Befehl" anhängen, dann wird der Wert auch vom FPU-Stack entfernt, wenn man den Wert unmittelbar danach nicht mehr in der FPU benötigt.

Dirk
TomCat
MemMaker-Benutzer
Beiträge: 87
Registriert: Do 1. Dez 2011, 17:16

Re: Sinus-Berechnung

Beitrag von TomCat »

hmm, hab einiges versucht, funktioniert leider nicht. kenne mich zu wenig mim Co-Prozessor aus.
TomCat
MemMaker-Benutzer
Beiträge: 87
Registriert: Do 1. Dez 2011, 17:16

Re: Sinus-Berechnung

Beitrag von TomCat »

hab mal folgendes ausprobiert, funzt aber leider nicht.

mov wert1000,1000

fild DWORD PTR[arcussinus_wert] ;von 0-1000
fidiv DWORD PTR[wert1000]

fld st(0)
fmul
fld st(0)
fld1
fsubr
fdiv
fsqrt
fld1
fpatan

fimul DWORD PTR[wert1000]
fistp DWORD PTR[winkel_wert]

:ende

Jemand ne Idee??
freecrac
DOS-Guru
Beiträge: 861
Registriert: Mi 21. Apr 2010, 11:44
Wohnort: Hamburg Horn

Re: Sinus-Berechnung

Beitrag von freecrac »

TomCat hat geschrieben:hab mal folgendes ausprobiert, funzt aber leider nicht.

mov wert1000,1000

fild DWORD PTR[arcussinus_wert] ;von 0-1000
fidiv DWORD PTR[wert1000]
fld st(0)
fmul
fld st(0)
fld1
fsubr
fdiv
fsqrt
fld1
fpatan

fimul DWORD PTR[wert1000]
fistp DWORD PTR[winkel_wert]

:ende

Jemand ne Idee??
Wofür sind die "fld st(0)" ?

Am besten noch einmal genau nachlesen im:
Intel® 64 and IA-32 Architectures Software Developer's Manuals.pdf
http://download.intel.com/design/proces ... 253665.pdf
[Chapter 3 Instruction Set Reference A - M]
->[3.1 Interpreting the Instruction Reference Pages]
->->[3.2 Instruction (A - M)]
FPATAN-Partial Arctangent Vol. 2A Seite 3-389

Dirk
Antworten