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

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