home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / fft32_a.zip / PCFFT32.ASM < prev    next >
Assembly Source File  |  1995-01-20  |  25KB  |  590 lines

  1.     .386
  2.     .387
  3.     .model flat
  4. ;              -------------------------------------
  5. ;                Fast Fourier Transformation (FFT)
  6. ;              -------------------------------------
  7. ;
  8. ; Filename          : PCFFT.ASM
  9. ; Written by        : J.G.G. Dobbe
  10. ;                   : 32 bit adaptation by R. Canup
  11. ; Function          : Fast Fourier Transform S/W. Two arrays hol-
  12. ;                     ding short-real floating point numbers (4
  13. ;                     bytes per real value) are used to perform
  14. ;                     the FFT after a call from C or Pascal compilers.
  15. ; Comment           : This module is written to link to:
  16. ;
  17. ;                       Gnu C 2.5.4. 32 bit OS/2 compiler 1/19/95
  18. ;
  19. ;                     An assembler switch (/dPSCL) must be entered
  20. ;                     if the object must be used with Pascal. It
  21. ;                     generates the required Pacal calling con-
  22. ;                     vention.
  23. ;
  24. ;                     Note: A coprocessor must be present when
  25. ;                           using this code!
  26. ;
  27. ; The C prototype for this routine is:
  28. ;
  29. ;       void Fft(float *Re, float *Im, int Pwr, int Dir);
  30. ;
  31. ; Performs Fast Fourier Transform on the arrays Re and Im. The
  32. ; length of the arrays is given as a power of two in variable
  33. ; "Pwr". Example: if array has 1024 values "Pwr" is 10 - since two to the
  34. ; 10th power is 1024.
  35. ;
  36. ; Variable "Dir" determines whether a normal or an inversed FFT
  37. ; will be performed:
  38. ;
  39. ;   Dir >= 1 => FFT           (Time domain to frequency domain)
  40. ;   Dir <= 0 => Inversed FFT  (Frequency domain to time domain)
  41. ;
  42. ; Example:
  43. ;
  44. ;   Fft( &Re, &Im, 12, -1);
  45. ;
  46. ; This would do an inverse fft on a pair of arrays with 4096 floating point
  47. ; values.
  48. ;
  49. ; No error-checking is performed on overflow. You can be sure no
  50. ; overflow occurs when each element of Re and Im, is smaller than
  51. ; the maximum value of:
  52. ;
  53. ;   3.4 E 38 / N      (N = Length of arrays Re and Im)
  54. ;
  55. ; The executable code for function Fft is placed in a common code segment.
  56. ; Local variables are stored in a data segment. Despite the
  57. ; propaganda that programs in OS/2 are all in one segment - the truth is that
  58. ; the Intel architecture won't allow writing to a code segment. In actuality
  59. ; the OS/2 model is more like a giant "small" model in a dos compiler: one
  60. ; segment for code, and one for data and stack. Since each of these segments
  61. ; has a limit of 1bffffffh (When a program bombs examine the data registers and
  62. ; segment limits) which is 448 megabytes - this is not much of a constraint. I
  63. ; would be very interested in seeing a program which coudn't fit in 448 mega-
  64. ; bytes.
  65. ; OS/2 traps out to an error if the calculations produce a denormalized result
  66. ; with the following initialization values.
  67.  
  68.  
  69. ; -------------- Constants used by FFT-main routine -----------------
  70.  
  71. ; CoProcessor initialization:
  72. ;
  73. ; Bit  Code   Use
  74. ;  0   IM     Invalid operation exception mask     0    Enabled
  75. ;  1   DM     Denormalized operand exception mask  0    Enabled
  76. ;  2   ZM     Zerodivide exception mask            0    Enabled
  77. ;  3   OM     Overflow exception mask              0    Enabled
  78. ;  4   UM     Underflow exception mask             1    Disabled
  79. ;  5   PM     Precision exception mask             1    Disabled
  80. ;  6   -      -                                    -    -
  81. ;  7   IEM    Interrupt enable mask                0    Enabled
  82. ;  8   PC     Precision control\                   1  - 64 bits
  83. ;  9   PC     Precision control/                   1  /
  84. ; 10   RC     Rounding control\                    0  - Nearest even
  85. ; 11   RC     Rounding control/                    0  /
  86. ; 12   IC     Infinity control                     1    Affine
  87. ; 13   -      -                                    -    -
  88. ; 14   -      -                                    -    -
  89. ; 15   -      -                                    -    -
  90.  
  91. CoCPUCmd        EQU     1330H                   ; CoCPU init code
  92.  
  93. IFDEF   PSCL
  94. ; These values may need changed if they are used with a 32 bit OS/2 Pascal
  95. ; Borland Pascal for dos values:
  96. BdRe            EQU     DWORD PTR [EBP+30]       ; "Re"-array
  97. BdIm            EQU     DWORD PTR [EBP+26]       ; "Im"-array
  98. BdPower         EQU               [EBP+24]       ; "Pwr"
  99. BdDir           EQU               [EBP+22]       ; "Dir"
  100.  
  101. ELSE
  102. ; The stack frame is as follows for Gnu C 2.5.4. :
  103. ;stack_frame STRUC
  104. ;    redi    dd  ?       ; register set caused by PUSHAD instruction
  105. ;    resi    dd  ?       ;         .
  106. ;    rebp    dd  ?       ;         .
  107. ;    resp    dd  ?       ;         .
  108. ;    rebx    dd  ?       ;         .
  109. ;    redx    dd  ?       ;         .
  110. ;    recx    dd  ?       ;         .
  111. ;    reax    dd  ?       ;         .
  112. ;    retaddr dd  ?       ; return address
  113. ;    BdRe    dd  ?       ; "Re" - array address
  114. ;    BdIm    dd  ?       ; "Im" - array address
  115. ;    BdPower dd  ?       ; "Pwr"- 32 bit integer value
  116. ;    BdDir   dd  ?       ; "Dir"- 32 bit integer value
  117. ;stack_frame ENDS
  118. ;
  119. ; Thus the offsets for the values are:
  120. ;
  121. BdRe            EQU     DWORD PTR [EBP+36]       ; "Re"-array
  122. BdIm            EQU     DWORD PTR [EBP+40]       ; "Im"-array
  123. BdPower         EQU     DWORD PTR [EBP+44]       ; "Pwr"
  124. BdDir           EQU     DWORD PTR [EBP+48]       ; "Dir"
  125. ;
  126. ; These defines allow constructs such as:
  127. ;       MOV EAX,BdRe
  128. ; instead of
  129. ;       MOV EAX,DWORD PTR [EBP+36]
  130.  
  131. ENDIF
  132.  
  133. .data
  134. AngleCounter    DD      (?)                     ; AngleCounter
  135. FftLength       DD      (?)                     ; Length of FFT-arrs
  136. FftPower        DD      (?)                     ; 2^FftPower = FftLen
  137. FlyDistance     DD      (?)                     ; Fly-distance
  138. Index1          DD      (?)                     ; Index1
  139. Index2          DD      (?)                     ; Index2
  140. Re1Pointer      DD      (?)                     ; Pnter to Re[Index1]
  141. Re2Pointer      DD      (?)                     ; Pnter to Re[Index2]
  142. Im1Pointer      DD      (?)                     ; Pnter to Im[Index1]
  143. Im2Pointer      DD      (?)                     ; Pnter to Im[Index2]
  144. TempR           DD      (?)                     ; TempR
  145. TempI           DD      (?)                     ; TempI
  146. CoCPUTemp       DW      (?)                     ; Temp data for CoCPU
  147. CoProcState     DB      94 DUP (?)              ; CoProc status area
  148.  
  149. CosArray        DD      -1.00000000000000       ; TurboPascal doesn't
  150.                 DD       0.00000000000000       ; accept this initia-
  151.                 DD       0.70710678118655       ; lized data to be in
  152.                 DD       0.92387953251129       ; the DATA segment
  153.                 DD       0.98078528040323
  154.                 DD       0.99518472667220
  155.                 DD       0.99879545620517
  156.                 DD       0.99969881869620
  157.                 DD       0.99992470183914
  158.                 DD       0.99998117528260
  159.                 DD       0.99999529380958
  160.                 DD       0.99999882345170
  161.                 DD       0.99999970586288
  162.                 DD       0.99999992646572
  163.                 DD      -1.00000000000000
  164.                 DD       0.00000000000000
  165.                 DD       0.70710678118655
  166.                 DD       0.92387953251129
  167.                 DD       0.98078528040323
  168.                 DD       0.99518472667220
  169.                 DD       0.99879545620517
  170.                 DD       0.99969881869620
  171.                 DD       0.99992470183914
  172.                 DD       0.99998117528260
  173.                 DD       0.99999529380958
  174.                 DD       0.99999882345170
  175.                 DD       0.99999970586288
  176.                 DD       0.99999992646572
  177.  
  178. SinArray        DD       0.00000000000000
  179.                 DD      -1.00000000000000
  180.                 DD      -0.70710678118655
  181.                 DD      -0.38268343236509
  182.                 DD      -0.19509032201613
  183.                 DD      -0.09801714032956
  184.                 DD      -0.04906767432742
  185.                 DD      -0.02454122852291
  186.                 DD      -0.01227153828572
  187.                 DD      -0.00613588464915
  188.                 DD      -0.00306795676297
  189.                 DD      -0.00153398018628
  190.                 DD      -0.00076699031874
  191.                 DD      -0.00038349518757
  192.                 DD       0.00000000000000
  193.                 DD       1.00000000000000
  194.                 DD       0.70710678118655
  195.                 DD       0.38268343236509
  196.                 DD       0.19509032201613
  197.                 DD       0.09801714032956
  198.                 DD       0.04906767432742
  199.                 DD       0.02454122852291
  200.                 DD       0.01227153828572
  201.                 DD       0.00613588464915
  202.                 DD       0.00306795676297
  203.                 DD       0.00153398018628
  204.                 DD       0.00076699031874
  205.                 DD       0.00038349518757
  206.  
  207. ScaleFactor     DD       0.50000000000000
  208.                 DD       0.25000000000000
  209.                 DD       0.12500000000000
  210.                 DD       0.06250000000000
  211.                 DD       0.03125000000000
  212.                 DD       0.01562500000000
  213.                 DD       0.00781250000000
  214.                 DD       0.00390625000000
  215.                 DD       0.00195312500000
  216.                 DD       0.00097656250000
  217.                 DD       0.00048828125000
  218.                 DD       0.00024414062500
  219.                 DD       0.00012207031250
  220.                 DD       0.00006103515625
  221.  
  222. ; -------------- Shuffle2Arr ----------------------------------------
  223.  
  224. ;* * * * * * * * * * * * * *
  225. ;*                         *
  226. ;* SUBROUTINE Shuffle2Arr; *
  227. ;*                         *
  228. ;* * * * * * * * * * * * * *
  229. ;
  230. ; Shuffles array a and b:
  231. ;
  232. ;  index  =  binair  --> shuffled index binair     index
  233. ;
  234. ;    0        000             000                    0
  235. ;    1        001             100                    4
  236. ;    2        010             010                    2
  237. ;    3        011             110                    6
  238. ;    4        100             001                    1
  239. ;    5        101             101                    5
  240. ;    6        110             011                    3
  241. ;    7        111             111                    7
  242. ;
  243. ;                                             2
  244. ;  n = word-length (3 in this example) => n =  log (Length Array a)
  245. ;  n must be > 0
  246. ;
  247. ; -------------- Start of code segment ------------------------------
  248. .code
  249. IFDEF   PSCL                                    ; Fft in asm
  250.         PUBLIC  Fft
  251. ELSE
  252.         PUBLIC  _Fft
  253. ENDIF
  254.  
  255. ; -------------- Variable definitions -------------------------------
  256.  
  257. Shuffle2Arr PROC    NEAR
  258.  
  259.         PUSH    EAX                     ; CPU regs on stack
  260.         PUSH    EBX                     ;
  261.         PUSH    ECX                     ;
  262.         PUSH    EDX                     ;
  263.         PUSH    ESI                     ;
  264.         PUSH    EDI                     ;
  265.                                         ; IN 32 bits we don't touch segments
  266.         MOV     EDX,[FftPower]          ; DL = Nr of bits shuffle-wrd
  267.         MOV     DH,DL                   ; DH = Nr of bits shuffle-wrd
  268.         MOV     ECX,[FftLength]         ; ECX = counter
  269.         MOV     ESI,00H                 ; First index (IndexOld)
  270. NextShuffleIndex:
  271.         MOV     EBX,ESI                 ; Find shuffled word
  272.         MOV     EAX,00H                 ;   EBX = source index
  273.         CLC                             ;   EAX = destination index
  274. NextB2:
  275.         RCR     EBX,1                   ;    ,-----------,   ,---,
  276.         RCL     EAX,1                   ;EBX=|,,5 4 3 2 1|->-| C |--,
  277.         DEC     DL                      ;    `-----------'   `---'  |
  278.         JG      NextB2                  ;    ,-----------,          |
  279.         MOV     DL,DH                   ;EAX=|1 2 3 4 5,,|-<--------'
  280.                                         ;    `-----------'
  281.         CMP     EAX,ESI                 ; IndexNew > IndexOld
  282.         JLE     SkipIndex2              ; No? Skip index
  283.         PUSH    EDX                     ; SAVE EDX
  284.  
  285.         MOV     EDI,BdRe                ; Ptr to first element of a
  286.         MOV     EBX,ESI                 ; Find IndexOld
  287.         SHL     EBX,2                   ;
  288.         PUSH    EBX                     ; Save for array b
  289.         ADD     EDI,EBX                 ;
  290.         FLD     DWORD PTR [EDI]         ; 0   a[IndexOld]
  291.         MOV     EBX,BdRe                ; Ptr to first element of a
  292.         SHL     EAX,2                   ; Find IndexNew
  293.         PUSH    EAX                     ; Save for array b
  294.         ADD     EBX,EAX                 ;
  295.         FLD     DWORD PTR [EBX]         ; 1   a[IndexNew]
  296.         FSTP    DWORD PTR [EDI]         ; a[IndexOld] = a[IndexNew]
  297.         FSTP    DWORD PTR [EBX]         ; a[Indexnew] = a[IndexOld]
  298.  
  299.         POP     EAX                     ;
  300.         MOV     EDI,BdIm                ; Ptr to first element of b
  301.         POP     EBX                     ; Find IndexOld
  302.         ADD     EDI,EBX                 ;
  303.         FLD     DWORD PTR [EDI]         ; 0   b[IndexOld]
  304.         MOV     EBX,BdIm                ; Prt to first element of b
  305.         ADD     EBX,EAX                 ;
  306.         FLD     DWORD PTR [EBX]         ; 1   b[IndexNew]
  307.         FSTP    DWORD PTR [EDI]         ; a[IndexOld] = a[IndexNew]
  308.         FSTP    DWORD PTR [EBX]         ; a[IndexNew] = a[IndexOld]
  309.  
  310.         POP     EDX                     ; Restore EDX
  311. SkipIndex2:
  312.         INC     ESI                     ; Next index
  313.         LOOP    NextShuffleIndex        ;
  314.  
  315.         POP     EDI                     ;
  316.         POP     ESI                     ;
  317.         POP     EDX                     ;
  318.         POP     ECX                     ;
  319.         POP     EBX                     ;
  320.         POP     EAX                     ;
  321.  
  322.         RET                             ; End of function Shuffle2Arr
  323. Shuffle2Arr     ENDP
  324.  
  325. ; --------------- NormalizeArr --------------------------------------
  326.  
  327. ;* * * * * * * * * * * * * * * * * * * * * * *
  328. ;*                                           *
  329. ;* SUBROUTINE NomalizeArr(Var Arr:FftArr);   *
  330. ;*                                           *
  331. ;* * * * * * * * * * * * * * * * * * * * * * *
  332. ;                                                        Bitlength
  333. ; Normalizes array Arr by dividing each element by Sqrt(2         )
  334.  
  335. NormalizeArr    PROC    NEAR
  336.  
  337. BdArr2  EQU     DWORD PTR [EBP+36]      ; GNU C 2.5.4. "Arr" pointer
  338.  
  339.         PUSHAD                          ; SAVE ALL THE REGISTERS
  340.         MOV     EBP,ESP                 ; SET UP BASE POINTER
  341.         MOV     EBX,[FftPower]          ; Save BitLength for later
  342.         MOV     ECX,[FftLength]         ;
  343.         MOV     ESI,BdArr2              ; ESI points to Arr2
  344.         MOV     EDI,OFFSET ScaleFactor  ;
  345.         DEC     EBX                     ;
  346.         SHL     EBX,2                   ; Take advantage of barrel shifter
  347.         ADD     EDI,EBX                 ;
  348.         FLD     DWORD PTR [EDI]         ; Scale-factor to coprocessor
  349. ScaleElement:
  350.         FLD     DWORD PTR [ESI]         ; Array-element to coprocessor
  351.         FMUL    ST,ST(1)                ; ST(0) = ST(0) * ST(1)
  352.         FSTP    DWORD PTR [ESI]         ;
  353.         ADD     ESI,04H                 ; Next element
  354.         LOOP    ScaleElement            ; All elemnts had?
  355.         POPAD                           ; Restore the registers
  356.         RET     04H                     ; End of function NormalizeArr
  357.  
  358. NormalizeArr    ENDP
  359.  
  360. ; -------------- Fft ------------------------------------------------
  361.  
  362. ;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  363. ;*                                                           *
  364. ;* void Fft(float *Re, float *Im, int Pwr, int Dir);         *
  365. ;*                                                           *
  366. ;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  367. ;
  368. ; FlyCount           ECX
  369. ; section            EDX
  370.  
  371. ; -------------- Entry code -----------------------------------------
  372.  
  373. IFDEF PSCL
  374.  
  375. Fft     PROC                            ; Pascal entry code
  376.  
  377. ELSE
  378.  
  379. _Fft    PROC                            ; C entry code
  380.  
  381. ENDIF
  382.  
  383. ; -------------- Actual FFT algorithm -------------------------------
  384.  
  385.         PUSHAD                          ; Save all the registers on the stack
  386.         MOV     EBP,ESP                 ; EBP = ESP
  387.         FSAVE   CoProcState             ; Save CoProc status and init
  388.         MOV     [CoCPUTemp],CoCPUCmd    ; Initialize CoProcessor
  389.         FLDCW   [CoCPUTemp]             ;
  390.  
  391.         MOV     ECX,BdPower             ; Length array = 2
  392.         MOV     [FftPower],ECX          ; Store power = WordLength
  393.         MOV     EAX,01H                 ;
  394. power:                                  ;                              ecx
  395.         SHL     EAX,CL                  ; Create actual size of array 2
  396.         MOV     [FftLength],EAX         ;
  397.         CALL    Shuffle2Arr             ; Shuffle arrays Re and Im
  398.  
  399.         MOV     EDX,01H                 ; Section = 1;
  400.         MOV     EAX,BdDir               ; if(BdDir>=0)AngleCounter=1;
  401.         CMP     EAX,00H                 ; else        AngleCounter=15;
  402.         JLE     InverseFft              ;
  403. NormalFft:
  404.         MOV     [AngleCounter],1        ; Normal  FFT
  405.         JMP     InitEnd                 ;
  406. InverseFft:
  407.         MOV     [AngleCounter],15       ; Inverse FFT
  408. InitEnd:
  409. MainLoop:
  410.         CMP     EDX,[FftLength]         ; while (section < N)
  411.         JL      SkipJump01              ;
  412.         JMP     Normalize               ;
  413. SkipJump01:
  414.         MOV     EAX,EDX                 ; FlyDistance=2 * section;
  415.         SHL     EAX,1                   ;
  416.         MOV     [FlyDistance],EAX       ;
  417.         MOV     EBX,OFFSET CosArray     ; 0 c=CosArray[AngleCounter];
  418.         MOV     EAX,[AngleCounter]      ;
  419.         DEC     EAX                     ;
  420.         SHL     EAX,2                   ;
  421.         ADD     EBX,EAX                 ;
  422.         FLD     DWORD PTR [EBX]         ;
  423.         MOV     EBX,OFFSET SinArray     ; 1 s=SinArray[AngleCounter];
  424.         ADD     EBX,EAX                 ;
  425.         FLD     DWORD PTR [EBX]         ;
  426.         FLD1                            ; 2 Qr=1.0;
  427.         FLDZ                            ; 3 Qi=0.0;
  428.         MOV     ECX,0FFFFFFFFH          ; for (FlyCount=0;FlyCount <
  429.                                         ;     (section-1); FlyCount++)
  430. ForLoop:
  431.         INC     ECX                     ;
  432.         MOV     EAX,EDX                 ;
  433.         DEC     EAX                     ;
  434.         CMP     ECX,EAX                 ;
  435.         JLE     SkipJump03              ;
  436.         JMP     ForLoopEnd              ;
  437. SkipJump03:
  438.         MOV     [Index1],ECX            ; Index1=FlyCount;
  439. Repeat1:
  440.         MOV     EAX,[Index1]            ; Index2=Index1 + section;
  441.         MOV     EBX,EAX                 ;
  442.         ADD     EAX,EDX                 ;
  443.         MOV     [Index2],EAX            ;
  444.  
  445.         SHL     EBX,02H                 ; EBX = offset to [Index1]
  446.         SHL     EAX,02H                 ;
  447.  
  448.         MOV     EDI,BdIm                ; Store pointer to Im[Index1]
  449.         MOV     ESI,EDI                 ;
  450.         ADD     EDI,EBX                 ;
  451.         MOV     [Im1Pointer],EDI        ;
  452.         ADD     ESI,EAX                 ; Store pointer to Im[Index2]
  453.         MOV     [Im2Pointer],ESI        ;
  454.  
  455.         FLD     DWORD PTR [ESI]         ; 4 Im[Index2] element->CoProc
  456.         FLD     ST(0)                   ; 5 Im[index2]
  457.         FMUL    ST(0),ST(2)             ; 5 Im[Index2]*Qi
  458.  
  459.         MOV     EDI,BdRe                ; Store pointer to Re[Index1]
  460.         MOV     ESI,EDI                 ;
  461.         ADD     EDI,EBX                 ;
  462.         MOV     [Re1Pointer],EDI        ;
  463.         ADD     ESI,EAX                 ; Store pointer to Re[Index2]
  464.         MOV     [Re2Pointer],ESI        ;
  465.  
  466.         FLD     DWORD PTR [ESI]         ; 6 Re[Index2]
  467.         FLD     ST(0)                   ; 7 Re[Index2]
  468.         FMUL    ST(0),ST(5)             ; 7 Re[Index2]*Qr
  469.         FSUB    ST(0),ST(2)             ; 7 Re[Index2]*Qr-Im[Index2]*Qi
  470.         FSTP    DWORD PTR TempR         ; Store at TempR and pop
  471.         FMUL    ST(0),ST(3)             ; 6 Re[Index2]*Qi
  472.         FLD     ST(2)                   ; 7 Im[Index2]
  473.         FMUL    ST(0),ST(5)             ; 7 Im[Index2]*Qr
  474.         FADD    ST(0),ST(1)             ; 7 Im[Index2]*Qr+Re[Index2]*Qi
  475.         FSTP    DWORD PTR TempI         ; Store at TempI and pop
  476.         FSTP    ST(0)                   ; Pop CoProcessor registers
  477.         FSTP    ST(0)                   ;
  478.         FSTP    ST(0)                   ;
  479.  
  480.         ;* * * * * * * * * * * * * *
  481.         ;* Re2=Re[Index1] - TempR  *
  482.         ;* * * * * * * * * * * * * *
  483.  
  484.         MOV     ESI,BdRe                ; Re-array
  485.         MOV     ESI,[Re1Pointer]        ;
  486.         FLD     DWORD PTR [TempR]       ; 0    TempR
  487.         FLD     DWORD PTR [ESI]         ; 1    Re[Index1]
  488.         FLD     ST(0)                   ; 2    Re[Index1]
  489.         FSUB    ST(0),ST(2)             ; 2    Re[Index1] - TempR
  490.         MOV     EDI,[Re2Pointer]        ;
  491.         FSTP    DWORD PTR [EDI]         ; Re[Index2]=Re[Index1]-TempR
  492.  
  493.         ;* * * * * * * * * * * * * *
  494.         ;* Re1=Re[Index1] + TempR  *
  495.         ;* * * * * * * * * * * * * *
  496.  
  497.         FADD    ST(0),ST(1)             ; 1    Re[Index1] + TempR
  498.         FSTP    DWORD PTR [ESI]         ; Re[Index1] += TempR
  499.         FSTP    ST(0)                   ; Pop CoProcessor register
  500.  
  501.         ;* * * * * * * * * * * * * *
  502.         ;* Im2=Im[Index1] - TempI  *
  503.         ;* * * * * * * * * * * * * *
  504.  
  505.         MOV     ESI,BdIm                ; ES = segment of Im-array
  506.         MOV     ESI,[Im1Pointer]        ;
  507.         FLD     DWORD PTR [TempI]       ; 0    TempI
  508.         FLD     DWORD PTR [ESI]         ; 1    Im[Index1]
  509.         FLD     ST(0)                   ; 2    Im[Index1]
  510.         FSUB    ST(0),ST(2)             ; 2    Im[Index1] - TempI
  511.         MOV     EDI,[Im2Pointer]        ;
  512.         FSTP    DWORD PTR [EDI]         ; Im[index2]=Im[Index1]-TempI
  513.  
  514.         ;* * * * * * * * * * * * * *
  515.         ;* Im1=Im[Index1] + TempI  *
  516.         ;* * * * * * * * * * * * * *
  517.  
  518.         FADD    ST(0),ST(1)             ; 1    Im[Index1] + TempI
  519.         FSTP    DWORD PTR [ESI]         ; Im[Index1] += TempI
  520.         FSTP    ST(0)                   ; Pop CoProcessor register
  521.  
  522.         MOV     EAX,[Index1]            ; Index1 += FlyDistance;
  523.         MOV     EBX,[FlyDistance]       ;
  524.         ADD     EAX,EBX                 ;
  525.         MOV     [Index1],EAX            ;
  526.         MOV     EBX,[FftLength]         ; Index1 > (N-1)?
  527.         DEC     EBX                     ;
  528.         CMP     EAX,EBX                 ;
  529.         JG      SkipJump02              ; No? To Repeat1
  530.         JMP     Repeat1                 ;
  531. SkipJump02:
  532.         FLD     ST(0)                   ; 4 Qi
  533.         FMUL    ST(0),ST(3)             ; 4 Qi*s
  534.         FLD     ST(2)                   ; 5 Qr
  535.         FMUL    ST(0),ST(4)             ; 5 Qr*s
  536.         FLD     ST(3)                   ; 6 Qr
  537.         FMUL    ST(0),ST(6)             ; 6 Qr*c
  538.         FSUB    ST(0),ST(2)             ; 6 Qr*c - Qi*s
  539.         FSTP    ST(4)                   ; Store and pop
  540.         FLD     ST(2)                   ; 6 Qi
  541.         FMUL    ST(0),ST(6)             ; 6 Qi*c
  542.         FADD    ST(0),ST(1)             ; 6 Qi*c + Qr*s
  543.         FSTP    ST(3)                   ; store and pop
  544.         FSTP    ST(0)                   ; Pop CoProcessor registers
  545.         FSTP    ST(0)                   ;
  546.         JMP     ForLoop                 ;
  547.  
  548. ForLoopEnd:
  549.         SHL     EDX,01H                 ; section     = section * 2;
  550.         INC     [AngleCounter]          ; AngleCounter=AngleCounter+1;
  551.         FSTP    ST(0)                   ; Pop CoProcessor registers
  552.         FSTP    ST(0)                   ;
  553.         FSTP    ST(0)                   ;
  554.         FSTP    ST(0)                   ;
  555.         JMP     MainLoop                ;
  556.  
  557. Normalize:
  558.         MOV     EAX,BdDir               ; if (BdDir == 1) NoNormalize;
  559.         CMP     EAX,01H                 ; else            Normalize;
  560.         JE      NoNormalize             ;
  561.         MOV     ESI,BdRe                ; Normalize Re
  562.         PUSH    ESI                     ;
  563.         CALL    NormalizeArr            ;
  564.  
  565.         MOV     ESI,BdIm                ; Normalize Im
  566.         PUSH    ESI                     ;
  567.         CALL    NormalizeArr            ;
  568. NoNormalize:
  569. FftEnd:
  570.         FRSTOR  CoProcState             ; Restore entire CoPU status
  571.         POPAD                           ; Restore CPU registers
  572.  
  573. ; -------------- Termination code -----------------------------------
  574.  
  575. IFDEF   PSCL                            ; Termination code for Pascal
  576.  
  577.         RET     0CH                     ; End of function Fft
  578. Fft     ENDP
  579.  
  580. ELSE                                    ; Termination code for C
  581.  
  582.         RET                             ; End of function Fft
  583. _Fft    ENDP
  584.  
  585. ENDIF
  586.  
  587. ; -------------- Assembler termination ------------------------------
  588.  
  589.                 END
  590.