.586P
.587
locals
jumps
.model flat,STDCALL
include win32.inc           ; some 32-bit constants and structures

L equ <LARGE>

;
; Define the external functions we will be linking to
;
extrn            BeginPaint:PROC
extrn            CreateWindowExA:PROC
extrn            DefWindowProcA:PROC
extrn            DispatchMessageA:PROC
extrn            EndPaint:PROC
extrn            ExitProcess:PROC
extrn            FindWindowA:PROC
extrn            GetMessageA:PROC
extrn            GetModuleHandleA:PROC
extrn            GetStockObject:PROC
extrn            InvalidateRect:PROC
extrn            LoadCursorA:PROC
extrn            LoadIconA:PROC
extrn            MessageBoxA:PROC
extrn            PostQuitMessage:PROC
extrn            RegisterClassA:PROC
extrn            ShowWindow:PROC
extrn            SetWindowPos:PROC
extrn            TextOutA:PROC
extrn            TranslateMessage:PROC
extrn            UpdateWindow:PROC
extrn            CreateFileA:PROC
extrn            GetFileSize:PROC
extrn            CloseHandle:PROC
extrn            GlobalAlloc:PROC
extrn            GlobalHandle:PROC
extrn            GlobalFree:PROC
extrn            ReadFile:PROC
extrn            WriteFile:PROC
extrn            GlobalMemoryStatus:PROC
extrn            GetWindowTextA:PROC
extrn            MessageBeep:PROC
;
; for Unicode support, Win32 remaps some functions to either the Ansi or
; Wide char versions.  We will assume Ansi for this example.
;
CreateWindowEx   equ <CreateWindowExA>
DefWindowProc    equ <DefWindowProcA>
DispatchMessage  equ <DispatchMessageA>
FindWindow       equ <FindWindowA>
GetMessage       equ <GetMessageA>
GetModuleHandle  equ <GetModuleHandleA>
LoadCursor       equ <LoadCursorA>
LoadIcon         equ <LoadIconA>
MessageBox       equ <MessageBoxA>
RegisterClass    equ <RegisterClassA>
TextOut          equ <TextOutA>

.data
copyright        db 'Ingenieurbro Baumann, Dorsten',0

lppaint          PAINTSTRUCT <?>
msg              MSGSTRUCT   <?>
wc               WNDCLASS    <?>
hInst            dd 0
newhwnd          dd 0                           ;handle of mainwnd
childhwnd1       dd 0                           ;handle of childwindow
childhwnd2       dd 0

szTitleName      db 'Win32 Assembly Program /* inv-real-FFT */'
zero             db 0
szAlternate      db '(Secondary)',0
szClassName      db 'ASMCLASS32',0
szPaint          db '*.fft wird retransformiert nach *it.flt',0
MSG_L            EQU ($-offset szPaint)-1
szTitleName1     db 'e:\<Ordner>\<name>.fft',0
szClassName1     db 'EDIT',0
szTitleName2     db 'START',0
szClassName2     db 'BUTTON',0

;eine Struktur fr eine Speicheranfrage
dwLenght         dd 32                  ;Lnge dieser Struktur in Byte
dwMemoryLoad     dd 0                   ;Auslastung physk. Speicher in %
dwTotalPhys      dd 0                   ;im System vorhandener Speicher
dwAvailPhys      dd 0                   ;verfgbarer physk. Speicher
dwTotalPageFile  dd 0                   ;im System vorh. Page-File-Gráe
dwAvailPageFile  dd 0                   ;verfgbare Page-File-Gráe
dwTotalVirtual   dd 0                   ;Gráe virtueller Systemspeicher
dwAvailVirtual   dd 0                   ;verfgbarer virtueller Speicher

Outdat1          db 40 dup (0)                  ;Zieldatei
Indat            db 40 dup (0)                  ;Quelldatei

hIndat           dd 0
hOutdat1         dd 0
lenIndat         dd 0
lenIndat2        dd 0
lpIndatBuf       dd 0    ;Adresse des beantragten Buffers 1
lenBuff1         dd 0    ;Lnge des Buffers 1
lpOutdatBuf      dd 0    ;Adresse des beantragten Buffers 2
lenBuff2         dd 0    ;Lnge des Buffers 2
count            dd 0    ;gelesene oder geschriebene Byte der letzten Operation
defControl       dw 0    ;Koprozessor Kontrollwort original
myControl        dw 0    ;mein privates Kontrollwort des Koprozessors
zwei             dd 2
c10241024        dd 1024*1024
einhalb          dq 0.5
minus            dq -1.0

.code
;-----------------------------------------------------------------------------
;
; This is where control is received from the loader.
;
start:

        push    L 0
        call    GetModuleHandle         ; get hmod (in eax)
        mov     hInst, eax              ; hInstance is same as HMODULE
                                        ; in the Win32 world
        push    L 0
        push    offset szClassName
        call    FindWindow
        or      eax,eax
        jz      reg_class

        mov     [zero], ' '             ; space to modify title string

reg_class:
;
; initialize the WndClass structure
;
        mov     [wc.clsStyle], CS_HREDRAW + CS_VREDRAW + CS_GLOBALCLASS
        mov     [wc.clsLpfnWndProc], offset WndProc
        mov     [wc.clsCbClsExtra], 0
        mov     [wc.clsCbWndExtra], 0

        mov     eax, hInst
        mov     wc.clsHInstance, eax

        push    L IDI_APPLICATION
        push    L 0
        call    LoadIcon
        mov     wc.clsHIcon, eax

        push    L IDC_ARROW
        push    L 0
        call    LoadCursor
        mov     wc.clsHCursor, eax

        mov     wc.clsHbrBackground, COLOR_WINDOW + 1
        mov     dword ptr wc.clsLpszMenuName, 0
        mov     dword ptr wc.clsLpszClassName, offset szClassName

        push    offset wc
        call    RegisterClass
        
        push    L 0                      ; lpParam
        push    hInst                    ; hInstance
        push    L 0                      ; menu
        push    L 0                      ; parent hwnd
        push    L 100                    ; height
        push    L 600                    ; width
        push    L CW_USEDEFAULT          ; y
        push    L CW_USEDEFAULT          ; x
        push    L WS_OVERLAPPEDWINDOW    ; Style
        push    offset szTitleName       ; Title string
        push    offset szClassName       ; Class name
        push    L 0                      ; extra style
        call    CreateWindowEx
        mov     newhwnd, eax

        push    L SW_SHOWNORMAL
        push    newhwnd
        call    ShowWindow

        push    newhwnd
        call    UpdateWindow

        ;EDIT-Child
        push    L 0
        push    hInst
        push    L 0
        push    newhwnd
        push    L 20
        push    L 256
        push    L 26
        push    L 5
        push    L (WS_CHILD or WS_CAPTION or WS_VISIBLE)
        push    offset szTitleName1
        push    offset szClassName1
        push    L 0
        call    CreateWindowEx
        mov     childhwnd1,eax

        ;BUTTON-Child
        push    L 0
        push    hInst
        push    L 0
        push    newhwnd
        push    L 50
        push    L 100
        push    L 10
        push    L 420
        push    L (WS_CHILD or 00000000h or WS_VISIBLE)
        push    offset szTitleName2
        push    offset szClassName2
        push    L 0
        call    CreateWindowEx
        mov     childhwnd2,eax

msg_loop:
        push    L 0
        push    L 0
        push    L 0
        push    offset msg
        call    GetMessage

        cmp     ax, 0
        je      end_loop

        push    offset msg
        call    TranslateMessage

        push    offset msg
        call    DispatchMessage

        jmp     msg_loop

end_loop:
        push    msg.msWPARAM
        call    ExitProcess

        ; we never get to here

;-----------------------------------------------------------------------------
WndProc          proc uses ebx edi esi, hwnd:DWORD, wmsg:DWORD, wparam:DWORD, lparam:DWORD
;
; WARNING: Win32 requires that EBX, EDI, and ESI be preserved!  We comply
; with this by listing those regs after the 'uses' statement in the 'proc'
; line.  This allows the Assembler to save them for us.
;
        LOCAL   theDC:DWORD

        cmp     wmsg, WM_DESTROY
        je      wmdestroy
        cmp     wmsg, WM_RBUTTONDOWN
        je      wmrbuttondown
        cmp     wmsg, WM_SIZE
        je      wmsize
        cmp     wmsg, WM_CREATE
        je      wmcreate
        cmp     wmsg, WM_LBUTTONDOWN
        je      wmlbuttondown
        cmp     wmsg, WM_PAINT
        je      wmpaint
        cmp     wmsg, WM_GETMINMAXINFO
        je      wmgetminmaxinfo
        cmp     wmsg, WM_CHAR
        je      wm_char
        cmp     wmsg, WM_COMMAND
        je      wmcommand

        jmp     defwndproc

wmcommand:
        ;EDIT-FELD
        mov     eax,lparam              ;handle of sending element
        cmp     eax,childhwnd1          ;handle of my element
        jne     wmcommand1              ;was it not
        mov     eax,wparam              ;HI:message, LO:ID
        sar     eax,16                  ;ax message
        cmp     ax,0300h                ;EN_CHANGE
        jne     wmcommand1              ;not EN_CHANGE
        ;Reaktion auf jede nderung des Textes im Edit-Feld
        jmp     finish                  ;ready

wmcommand1:
        ;BUTTON mit START
        mov     eax,lparam              ;handle of sending element
        cmp     eax,childhwnd2          ;my ?
        jne     defwndproc              ;nein

        ;Dateinamen aus Edit-Feld nach Indat kopieren
        push    L 40                    ;count asciis
        push    offset Indat            ;to buffer
        push    childhwnd1              ;from element with this handle
        call    GetWindowTextA          ;copy text

        ;Dateinamen fr Ausgabedatei kopieren
        cld
        mov     ecx,L 40
        mov     esi,offset Indat
        mov     edi,offset Outdat1
        rep     movsb

        ;*.fft ndern in *it.flt
        mov     esi,offset Outdat1
        mov     ecx,L 40
search: mov     al,[esi]
        cmp     al,'.'
        je      change
        inc     esi
        loop    search

change: mov     ax,'ti'
        mov     [esi],ax
        add     esi,L 2
        mov     eax,'tlf.'
        mov     [esi],eax

        jmp     doit                    ;Start

wmpaint:
        push    offset lppaint
        push    hwnd
        call    BeginPaint
        mov     theDC, eax

        push    L MSG_L           ; length of string
        push    offset szPaint    ; string
        push    L 5               ; y
        push    L 5               ; x
        push    theDC             ; the DC
        call    TextOut

        push    offset lppaint
        push    hwnd
        call    EndPaint

        mov     eax, 0
        jmp     finish

wmcreate:
        mov     eax, 0
        jmp     finish

defwndproc:
        push    lparam
        push    wparam
        push    wmsg
        push    hwnd
        call    DefWindowProc
        jmp     finish

wmdestroy:
        push    L 0
        call    PostQuitMessage
        mov     eax, 0
        jmp     finish

wmlbuttondown:

        jmp     finish

wmrbuttondown:

        ;Fenster berholen
        push    L 0
        push    L 0
        push    hwnd
        call    InvalidateRect          

        jmp     finish

wmsize:
        mov     eax, 0
        jmp     finish

wmgetminmaxinfo:
        mov     ebx, lparam  ; ptr to minmaxinfo struct
        mov     [(MINMAXINFO ptr ebx).mintrackposition_x] , 350
        mov     [(MINMAXINFO ptr ebx).mintrackposition_y] , 60
        mov     eax, 0
        jmp     finish

wm_char:
        jmp finish

doit:   ;Koprozessor Kontrollwort setzen
        fstcw   defControl
        mov     ax,defControl
        or      ax,0001001110111111b    ;nchste oder gerade Zahl bei 0.5
        mov     myControl,ax
        fldcw   myControl
        feni

        ;Eingangsdatendatei ffnen
        push    L 0                     ;hTemplateFile
        push    L 020h                  ;dwAttrsAndFlag
        push    L 04h                   ;dwCreate
        push    L 0                     ;lpSecurityAttributes
        push    L 0                     ;dwShareMode
        push    L 080000000h            ;Generic_Read
        push    offset Indat            ;Dateinamenadresse
        call    CreateFileA             ;ffnen
        mov     hIndat,eax              ;Handle

        ;Lnge der Datei erfragen
        push    L 0                     ;lpdwFileSizeHigh
        push    eax                     ;Handle
        call    GetFileSize
        mov     lenIndat,eax            ;Lnge in Byte
        mov     ebx,eax
        sar     eax,1
        mov     lenIndat2,eax           ;Hlfte

        ;Ausgangsdatendatei ffnen
        push    L 0                     ;hTemplateFile
        push    L 020h                  ;dwAttrsAndFlag
        push    L 04h                   ;dwCreate
        push    L 0                     ;lpSecurityAttributes
        push    L 0                     ;dwShareMode
        push    L 040000000h            ;Generic_Write
        push    offset Outdat1          ;Dateinamenadresse
        call    CreateFileA             ;ffnen
        mov     hOutdat1,eax            ;Handle

        ;Speicher fr Eingangsdaten beantragen
        mov     eax,lenIndat
        mov     lenBuff1,eax            ;merken
        mov     ebx,eax
        sar     ebx,1                   ;halbieren fr Buffer 2
        mov     lenBuff2,ebx            ;merken
        add     eax,ebx                 ;zusammen beantragen

        push    eax
        push    L 0
        call    GlobalAlloc             ;Speicher beantragen
        cmp     eax,L 0                 ;erfolgreich ?
        je      Fehler                  ;nein

        ;Anfangsadressen zuweisen
        mov     lpIndatBuf,eax          ;zugewiesene Anfangsadresse
        add     eax,lenBuff1            ;+ Lnge groáer Buffer
        mov     lpOutdatBuf,eax         ;= Adresse OutdatBuf

        call    realFFTinv              ;Tranformation

        ;Outdat1 schlieáen
        push    hOutdat1
        call    CloseHandle

        push    lpIndatBuf              ;Handle erfragen fr IndatBuf
        call    GlobalHandle
        push    eax
        call    GlobalFree              ;IndatBuffer zurck ans System

finish: ret
        
WndProc          endp
;-----------------------------------------------------------------------------
realFFTinv   proc

        LOCAL   cntn:DWORD,cntn2:DWORD,bits:DWORD,maxIndex:DWORD,\
k:DWORD,istep:DWORD,wr:DWORD,wi:DWORD,j:DWORD,jk:DWORD,\
ik:DWORD,tr:DWORD,ti:DWORD,help:DWORD,cntErg:DWORD,\
vz:DWORD,i:DWORD,m:DWORD,arg:DWORD,\
jadr:DWORD,jkadr:DWORD,ikadr:DWORD,iadr:DWORD,n:DWORD,maxIndex2:DWORD,\
stat:WORD

        ;make fft
        ;einige Vorbereitungen
        mov     eax,lenIndat            ;Anzahl der Byte in Indat
        sar     eax,2                   ;/4=Anzahl der Abtastwerte
        mov     cntn,eax                ;lokal merken
        mov     ebx,eax
        sar     eax,1                   ;/2=halbe Anzahl
        mov     cntn2,eax               ;lokal merken
        dec     ebx                     ;maxIndex=Anzahl - 1
        mov     maxIndex,ebx            ;merken
        inc     ebx
        sar     ebx,1
        dec     ebx
        mov     maxIndex2,ebx

        ;Spektrum zerlegen in gerade und ungerade Fkt. bzgl. Frequenzachse
        ;1. Durchgang (blau)
        ;Realteil des Spektrums laden (= 1. Dateihlfte)
        push    L 0                     ;keine overlapped-Struktur
        push    offset count            ;gelesene Byte
        push    lenIndat2               ;zu lesende Byte
        push    lpOutdatBuf             ;Adresse des Buffers
        push    hIndat                  ;Handle der Datei
        call    ReadFile                ;lesen

        ;a0/2 eintragen
        mov     esi,lpOutdatBuf
        mov     eax,dword ptr [esi]     ;a0/2
        mov     edi,lpIndatBuf
        mov     dword ptr [edi],eax     ;ablegen

        ;Zerlegung: zuerst Realteil blau
        mov     ecx,L 1                 ;Zhler bis maxIndex2
dg1:    ;jadr
        mov     ebx,ecx
        mov     j,ebx
        sal     ebx,2
        add     ebx,lpOutdatBuf
        ;jadr
        mov     edx,cntn2
        sub     edx,ecx
        sal     edx,2
        add     edx,lpOutdatBuf
        ;a1=1/2[R(n)+R(N-n)] und a2=1/2[R(n)-R(N-n)]
        mov     eax,dword ptr [edx]     ;R(N-n)
        mov     help,eax
        fld     help
        mov     eax,dword ptr [ebx]     ;R(n)
        mov     help,eax
        fld     help
        fld     st
        fadd    st,st(2)                   
        fmul    einhalb                 ;1/2*(R(n)+R(N-n))
        fld     st(1)
        fsub    st,st(3)
        fmul    einhalb                 ;1/2*(R(n)-R(N-n))
        fldpi
        fimul    j
        fmul    minus
        fidiv   cntn2
        fst     arg
        fsin
        fmul    minus
        fmul    st,st(1)
        fadd    st,st(2)                ;Re(n) blau
        fstp    help
        mov     eax,help
        mov     ebx,j
        sal     ebx,2
        add     ebx,lpIndatBuf
        mov     dword ptr [ebx],eax     ;ablegen

        fld     arg                     ;Im(n) blau
        fcos
        fmul    st,st(1)
        fstp    help
        mov     eax,help
        mov     ebx,j
        add     ebx,cntn2
        sal     ebx,2
        add     ebx,lpIndatBuf
        mov     dword ptr [ebx],eax     ;ablegen
        ffree   st
        ffree   st(1)
        ffree   st(2)
        ffree   st(3)
        inc     ecx
        cmp     ecx,maxIndex2
        jle     dg1

        ;2. Durchgang (rot)
        ;Imaginrteil des Spektrums laden (= 2. Dateihlfte)
        push    L 0                     ;keine overlapped-Struktur
        push    offset count            ;gelesene Byte
        push    lenIndat2               ;zu lesende Byte
        push    lpOutdatBuf             ;Adresse des Buffers
        push    hIndat                  ;Handle der Datei
        call    ReadFile                ;lesen

        ;b0/2 eintragen
        mov     esi,lpOutdatBuf
        mov     eax,dword ptr [esi]     ;b0/2
        mov     ebx,cntn2               ;Anzahl
        sal     ebx,2                   ;*4=Offset
        add     ebx,lpIndatBuf          ;+Basis=Adresse
        mov     dword ptr [ebx],eax     ;ablegen

        ;Zerlegung: jetzt Realteil rot
        mov     ecx,L 1                 ;Zhler bis maxIndex2
dg2:    ;jadr
        mov     ebx,ecx
        mov     j,ebx
        sal     ebx,2
        add     ebx,lpOutdatBuf
        ;jadr
        mov     edx,cntn2
        sub     edx,ecx
        ;inc     edx
        sal     edx,2
        add     edx,lpOutdatBuf
        ;a3=1/2[I(n)+I(N-n)] und a4=1/2[I(n)-I(N-n)]
        mov     eax,dword ptr [edx]     ;I(N-n)
        mov     help,eax
        fld     help
        mov     eax,dword ptr [ebx]     ;I(n)
        mov     help,eax
        fld     help
        fld     st
        fadd    st,st(2)                   
        fmul    einhalb                 ;1/2*(I(n)+I(N-n))
        fld     st(1)
        fsub    st,st(3)
        fmul    einhalb                 ;1/2*(I(n)-I(N-n))
        fldpi
        fimul   j
        fmul    minus
        fidiv   cntn2
        fst     arg
        fcos
        fmul    minus
        fmul    st,st(2)
        mov     eax,j
        sal     eax,2
        add     eax,lpIndatBuf
        mov     ebx,dword ptr [eax]
        mov     help,ebx
        fadd    help
        fstp    help
        mov     ebx,help
        mov     dword ptr [eax],ebx     ;Re(n) komplett
        mov     eax,j
        add     eax,cntn2
        sal     eax,2
        add     eax,lpIndatBuf
        mov     ebx,dword ptr [eax]
        mov     help,ebx
        fld     help
        fadd    st,st(1)
        fld     arg
        fsin
        fmul    minus
        fmul    st,st(3)
        faddp   st(1),st
        fstp    help
        mov     ebx,help
        mov     dword ptr [eax],ebx     ;Im(n) komplett
        ffree   st
        ffree   st(1)
        ffree   st(2)
        ffree   st(3)
        inc     ecx
        cmp     ecx,maxIndex2
        jle     dg2

        ;Bit-Breite des Index bestimmen falls weniger als 32 Bit Anzahl
        fld1
        fild    cntn                    ;1
        fyl2x                           ;logarithmus dualis cnt
        fistp   bits                    ;hchtes Bit der Lnge  z.B. 1000b=3
        dec     bits                    ;hchstes Bit im Index0 dann 0111b=2
        dec     bits                    ;1. u. 2. Hlfte bleiben erhalten

        ;in-place-bit-reverse-shuffling
        mov     edx,L 0                 ;Zhler
rodel1: mov     esi,edx                 ;Index Eingangsfeld
        mov     edi,edx                 ;clear
        mov     ecx,bits                ;Bitbreite Index
mir:    mov     ebx,bits
        sub     ebx,ecx                 ;Offset des gesp. Bit
        bt      esi,ecx                 ;in esi teste Bit Nr. ecx
        jnc     noset                   ;dieses Bit ist nicht gesetzt
        bts     edi,ebx                 ;set mirrored
        jmp     set
noset:  btr     edi,ebx
set:    dec     ecx                     ;next bit
        cmp     ecx,L 0                 ;alle?
        jge     mir                     ;nein        
        cmp     esi,edi                 ;neuer Index gráer als Alter ?
        jge     letitbe                 ;nein
        sal     esi,2                   ;Index0 * 4 = Offset
        add     esi,lpIndatBuf          ;Basis Source
        sal     edi,2                   ;Index0 * 4 = Offset
        add     edi,lpIndatBuf          ;Basis Dest
        mov     eax,dword ptr [esi]     ;source word
        push    eax                     ;merken
        mov     eax,dword ptr [edi]
        mov     dword ptr [esi],eax     ;destination word
        pop     eax
        mov     dword ptr [edi],eax
letitbe:inc     edx                     ;Index + 1
        cmp     edx,maxIndex            ;bis maxIndex2
        jle     rodel1                  ;next

        ;Indat schlieáen
        push    hIndat
        call    CloseHandle
;***************************checkedcheckedchecked*****************************

        ;jetzt die eigentliche Transformation
trans:  mov     eax,cntn2        ;cntn2
        mov     k,eax
        mov     edx,L 1          ;Variable l = 1

while:  cmp     edx,k                   ;while l<k
        jge     readyfft

                mov     eax,edx
                sal     eax,1
                mov     istep,eax

                mov     ecx,L 1                 ;for m=1 to l step 1
                mov     m,ecx
                for1:   mov     eax,L 1         ;eins
                        sub     eax,ecx         ;1-m
                        mov     help,eax        ;zwischenspeichern
                        fild    help            ;laden
                        mov     help,edx        ;l
                        fidiv   help            ;(1-m)/l
                        fldpi                   ;pi
	      fmul     minus
                        fmulp   st(1)           ;(1-m)/l*pi
                        fld     st(0)
                        fcos                    ;cos((1-m)/l*pi)
                        fstp    wr              ;=wr
                        fsin                    ;-sin((1-m)/l*pi)
                        fmul    minus
                        fstp    wi              ;=wi   ;checked, seems o.k.
                        mov     m,ecx           ;Schleifenvariable uáere Schleife retten            

                        for2:   mov     i,ecx                   ;for i=m to k step istep
                                ;Indizes
                                add     ecx,edx                 ;i + l
                                mov     j,ecx                   ;=j
                                add     ecx,k                   ;j + k
                                mov     jk,ecx                  ;= jk
                                mov     ecx,i                   ;i
                                add     ecx,k                   ;i + k
                                mov     ik,ecx                  ;= ik
                                ;Adresse Index j
                                mov     ebx,lpIndatBuf
                                mov     eax,j
                                dec     eax
                                sal     eax,2
                                add     eax,ebx
                                mov     jadr,eax
                                ;Adresse Index jk
                                mov     eax,jk
                                dec     eax
                                sal     eax,2
                                add     eax,ebx
                                mov     jkadr,eax
                                ;Adresse Index i
                                mov     eax,i
                                dec     eax
                                sal     eax,2
                                add     eax,ebx
                                mov     iadr,eax
                                ;Adresse Index ik
                                mov     eax,ik
                                dec     eax
                                sal     eax,2
                                add     eax,ebx
                                mov     ikadr,eax
                                ;tr ausrechnen
                                fld     wr                      ;wr laden
                                mov     eax,jadr
                                fmul    dword ptr [eax]         ;Abtastwert laden                                
                                fld     wi                      ;wi laden
                                mov     eax,jkadr
                                fmul    dword ptr [eax]         ;Abtastwert laden                                
                                fsubp   st(1),st                ;Differenz tr
                                fstp    tr                      ;merken
                                ;ti ausrechnen
                                mov     eax,jkadr
                                fld     dword ptr [eax]         ;Abtastwert                                
                                fmul    wr                      ;wr * fk(j+k)
                                fld     wi
                                mov     eax,jadr                ;Adresse Abtastwert fk(j)
                                mov     eax,dword ptr [eax]     ;Abtastwert
                                mov     help,eax
                                fmul    help
                                faddp   st(1),st                ;Summe ti
                                fstp    ti                      ;merken
                                ;fk(j) ausrechnen checked
                                mov     eax,iadr
                                fld     dword ptr [eax]         ;Abtastwert fk(i)                                
                                fsub    tr                      ;neuer fk(j)
                                mov     eax,jadr                               
                                fstp    dword ptr [eax]         ;ablegen Ergebnis
                                ;fk(j+k) ausrechnen
                                mov     eax,ikadr
                                fld     dword ptr [eax]         ;Abtastwert fk(i+k)                               
                                fsub    ti                      ;-ti=neuer fk(j+k)
                                mov     eax,jkadr               ;Index jk                                
                                fstp    dword ptr [eax]         ;Ergebnis ablegen
                                ;fk(i) ausrechnen
                                mov     ebx,iadr
                                fld     dword ptr [ebx]         ;fk(i)                               
                                fadd    tr                      ;+tr=neuer fk(i)                               
                                fstp    dword ptr [ebx]         ;Ergebnis ablegen
                                ;fk(i+k) ausrechnen
                                mov     ebx,ikadr               ;Index ik
                                fld     dword ptr [ebx]         ;Wert^                                
                                fadd    ti                      ;+ti                                
                                fstp    dword ptr [ebx]         ;Ergebnis ablegen
                        ;innere Schleife                                      
                        mov     ecx,i           ;Schleifenvariable
                        add     ecx,istep       ;Step
                        cmp     ecx,k           ;Abbruch
                        jle     for2            ;next i

                inc     m               ;Schleifenvariable m
                mov     ecx,m           
                cmp     ecx,edx         ;Abbruch
                jle     for1            ;next m

        mov     edx,istep               ;l=istep
        jmp     while                   ;wend

readyfft:
        ;jmp     write

        ;Imaginrteile zwischenspeichern
        mov     esi,lpIndatBuf
        mov     eax,cntn2
        inc     eax
        sal     eax,2
        add     esi,eax
        mov     edi,lpOutdatBuf
        mov     ecx,cntn2
        dec     eax
        cld
        rep     movsd

        ;der Ausreiáer (erster Wert im Imaginrteil wird allerletzter Abtastwert)
        mov     eax,cntn2
        inc     eax
        sal     eax,2
        add     eax,lpIndatBuf
        mov     ebx,dword ptr [eax]
        mov     eax,cntn
        sal     eax,2
        add     eax,lpIndatBuf
        mov     dword ptr [eax],ebx


        ;sortieren und schreiben 0,2,4,... nach OutdatBuf
        mov     ecx,cntn2               ;Anzahl Abtastwerte halbe
        mov     esi,lpIndatBuf
        mov     eax,maxIndex2
        sal     eax,2
        add     esi,eax

        mov     edi,lpIndatBuf
        mov     eax,maxIndex
        dec     eax
        sal     eax,2
        add     edi,eax
wloop:  mov     eax,dword ptr [esi]     ;Abtastwert
        mov     dword ptr [edi],eax
        sub     esi,L 4
        sub     edi,L 8
        loop    wloop                   ;nchsten

        ;sortieren und schreiben 1,3,5,... nach OutdatBuf
        mov     ecx,maxIndex2           ;Anzahl Abtastwerte halbe
        mov     esi,lpOutdatBuf
        mov     edi,lpIndatBuf
        add     edi,L 4        
wloop1: mov     eax,dword ptr [esi]     ;Abtastwert
        mov     dword ptr [edi],eax
        add     esi,L 4
        add     edi,L 8
        loop    wloop1                  ;nchsten

        ;Buffer leerschreiben
write:  push    L 0
        push    offset count
        mov     eax,cntn
        sal     eax,2
        push    eax
        push    lpIndatBuf
        push    hOutdat1
        call    WriteFile

        push    L 0
        call    MessageBeep

        ret

realFFTinv   endp
;-----------------------------------------------------------------------------

Fehler: push    L 0
        call    MessageBeep
        jmp     finish

;-----------------------------------------------------------------------------
public WndProc
ends
end start
