Gelöst: Meldung ML.exe "Statement too complex" + SSE Fehler



  • Guten Abend zusammen,

    Ich erstelle ein Variablenarray und erhalte beim kompilieren diese Meldung.

    In meinem bisherigen Programm waren diese Daten wie folgt angelegt:

    koo dd 250.0
    		dd 50.0
    		dd 250.0
    		dd 60.0
    		dd 250.0
    		dd 70.0
    		dd 250.0
    		dd 80.0
    		dd 250.0
    		dd 90.0
    		dd 250.0
    		dd 100.0
    		dd 250.0
    		dd 110.0
    		dd 250.0
    		dd 120.0
    		dd 250.0
    		dd 130.0
    		dd 250.0
    		dd 140.0
    		dd 250.0
    		dd 150.0
    

    Davon standen etwa 150 Einträge untereinander...
    (Das sind alles Koordinaten von Bildschirmpunkten X,Y und Z immer im Wechsel)

    Ich möchte mein "Array" nun aber getrennt nach X, Y und Z anlegen:

    koox 	dd 	250.0,270.0,330.0,330.0,350.0,350.0,330.0,270.0,270.0,250.0,250.0,290.0,290.0,310.0,310.0,290.0,330.0
    

    und zwar eben diese 150 Einträge... ab dem 51. Eintrag erhalte ich aber diese Meldung.

    Habe ich hier was übersehen?

    Gruß, Nicky



  • 1. benutz die richtige Typ: REAL4. DD/DQ/DT akzeptieren FP Werte nur aus Kompatibilitätsgründen.
    2. MASM hat eine maximale Zeilenlänge, die bei ca. 260 Zeichen liegt. Du musst die Zeile aufteilen.



  • masm schrieb:

    1. benutz die richtige Typ: REAL4. DD/DQ/DT akzeptieren FP Werte nur aus Kompatibilitätsgründen.
    2. MASM hat eine maximale Zeilenlänge, die bei ca. 260 Zeichen liegt. Du musst die Zeile aufteilen.

    Hallo,

    Array funktioniert...

    Nun habe ich meinen FPU Abschnitt nach SSE umgeschrieben... Leider verabschiedet sich hierbei die Anwendung 🙄

    mov edi, offset koox	;EDI = X Wert
        				mov esi, offset kooy	;ESI = Y Wert
    
        				mov ecx,13d		    			
        	drehenlinks:
    
        	.xmm			
        				;fld dword ptr [edi]
        				;fsub mm_x
        				;fstp dword ptr [edi]
    
        				movups xmm0, [edi]
        				subps xmm0, [mm_x]
        				movups [edi], xmm0
    
        				;fld dword ptr [esi]
        				;fsub mm_y
        				;fstp dword ptr [esi]
    
        				movups xmm0, [esi]
        				subps xmm0, [mm_y]
        				movups [esi], xmm0
    
        				;fld dword ptr [edi]
        				;fmul cos1
        				movups xmm1, [edi]
        				mulps xmm1, [cos1]
        				;fld dword ptr [esi]
        				;fmul sin1
        				movups xmm0, [esi]
        				mulps xmm0, [sin1]
        				;fsub
        				subps xmm1, xmm0
        				;fadd mm_x
        				addps xmm1, [mm_x]
        				;fstp tmpx
        				movups [tmpx], xmm1
    
        				;fld sin1
        				movups xmm0, [edi]
        				;fmul dword ptr [edi]
        				mulps xmm0, [sin1]
        				;fld cos1
        				movups xmm1, [esi]
        				;fmul dword ptr [esi]
        				mulps xmm1, [cos1]
        				;fadd
        				addps xmm0, xmm1
        				;fadd mm_y
        				addps xmm0, [mm_y]
        				;fstp dword ptr [esi]
        				movups [esi], xmm0
    
        				;fld tmpx
        				movups xmm0, [tmpx]
        				;fstp dword ptr [edi]
        				movups [edi], xmm0
    
       .486 			
        				add edi, 16d
        				add esi, 16d
        				dec ecx
        				jnz drehenlinks
    

    SSE rechnet das selbe wie die auskommentierten FPU Befehle. (Sollte zumindest)

    Für einen Tipp bin ich wie immer sehr dankbar...

    Gruß, Nicky



  • was sagt den dein Debugger(z.B. OllyDbg) dazu?
    Ich geh davon aus das es am alignment scheiter: die vektoriellen (packed) Befehle (add/sub/mulps) benötigen ebenfalls ein alignment von 16.
    Die jetzige Implementation ist höchstwahrscheinlich wesentlich langsamer als die FPU Version: sorg für das richte Ausrichtung und verwerf MOVUPS. Außerdem hast du 8 XMM Register zur Verfügung: genügend Platz um Zwischenergebnisse zu halten:

    movaps xmm0, [edi]  ; x
        movaps xmm1, [esi]  ; y
        subps xmm0, [mm_x]  ; dx = x-mm_x
        subps xmm1, [mm_y]  ; dy = y-mm_y
        movaps xmm2,xmm0
        movaps xmm3,xmm1
        mulps xmm0,[cos1]   ; = dx*cos(1°)
        mulps xmm1,[sin1]   ; = dy*sin(1°)
        mulps xmm2,[sin1]   ; = dx*sin(1°)
        mulps xmm3,[cos1]   ; = dy*cos(1°)
        subps xmm0,xmm1     ; dx*cos(1°) - dy*sin(1°)
        addps xmm2,xmm3     ; dx*sin(1°) + dy*cos(1°)
        addps xmm0,mm_x     ; dx*cos(1°) - dy*sin(1°) + mm_x
        addps xmm2,mm_y     ; dx*sin(1°) + dy*cos(1°) + mm_y
        movaps [edi], xmm0
        movaps [esi], xmm2
    


  • BTW: den Befehlssatz wählt man einmal am Anfang des Quellcodes aus (.486, .xmm). Das'd'-Suffix ist im Übrigen auch sehr gewöhnungsbedürftig, zumal es keine Sicherheit gibt (nur das 't'-Suffix ist eindeutig ;-)).



  • Hallo,

    Die Anweisung .486 würde tatsächlich am Anfang ausreichen, jedoch muss
    ich .xmm unmittelbar vor den Code setzen der SSE Befehle enthält.
    Ich erhalte sonst jede Zeile mit SSE Befehlen beim kompilieren als Fehler angezeigt.

    .486
    .model flat, stdcall
    .xmm
    
        option casemap :none
    
    include ..\include\windows.inc 
    include ..\include\kernel32.inc
    

    ------------------------------

    .code
    .xmm
    
    start:
          call Init
          call Main
          invoke ExitProcess,eax
    

    Ist beides nicht möglich...

    Jedenfalls habe ich mir deinen Hinweis, das auch subps, addps, divps die
    Ausrichtung brauchen nochmal überlegt und habe den Code etwas umgeschrieben:

    mov edi, offset koox	;EDI = X Wert
        				mov esi, offset kooy	;ESI = Y Wert
    
        				mov ecx,13d		;Gesamtzahl des Array in Byte / 16 ergibt die Anzahl der Punkte
    
        	drehenlinks:
    
        	.xmm		
    
                    movups xmm0,  [edi]
        			movups xmm1, [mm_x]
        			subps xmm0, xmm1
        			movups [edi], xmm0
    
        			movups xmm0, [esi]
        			movups xmm1, [mm_y]
        			subps xmm0, xmm1
        			movups [esi], xmm0
    
        		    movups xmm0, [edi]
        			movups xmm1, [cos1]
        			mulps xmm0, xmm1
    
        			movups xmm1, [esi]
        			movups xmm2, [sin1]
        			mulps xmm1, xmm2
    
        			subps xmm0, xmm1
    
        			movups xmm1, [mm_x]
        			addps xmm1, xmm0
    
        			movups [tmpx], xmm1
    
        			movups xmm0, [edi]
    
        			movups xmm1, [sin1]
        			mulps xmm0, xmm1
    
        			movups xmm1, [esi]
        			movups xmm2, [cos1]
    
        			mulps xmm1, xmm2
    
        			addps xmm0, xmm1
    
        			movups xmm1, [mm_y]
        			addps xmm0, xmm1
    
        			movups [esi], xmm0
    
        			movups xmm0, [tmpx]
                    movups [edi], xmm0
    
       		.486		
        				add edi, 16d
        				add esi, 16d
        				dec ecx
        				jnz drehenlinks
    

    Die einzigste Möglichkeit ist die Daten für jede Operation erst in die
    Register zu schreiben und dann den mathematischen Befehl nur auf die Register
    anzuwenden. So läuft es jedenfalls bei mir ohne Probleme.

    Aus irgendeinem Grund bekomme ich mit movaps keine Daten in die Register
    geschrieben, dann stürzt das Programm ab.

    Die Anweisung ALIGN 16 habe ich auch schon überall mal platziert gehabt,
    jedoch immer Absturz des Programms.

    Ob es langsamer ist als der FPU Teil weiß ich nicht, ich denke die WinApi
    tut ihr bestes um das Programm etwas zu bremsen 😃

    Gruß, Nicky



  • masm schrieb:

    Die jetzige Implementation ist höchstwahrscheinlich wesentlich langsamer als die FPU Version: sorg für das richte Ausrichtung und verwerf MOVUPS.

    Hallo masm,

    ich habe mal mit QueryPerformanceCounter (versucht) die Geschwindigkeit
    des SSE Abschnittes und des FPU Abschnittes zu messen..

    Wenn ich jeweils Anfangs- und Endwert subtrahiere erhalte ich bei
    SSE zwischen 3 und 4, bei FPU zwischen 9 - 12.

    Von der Geschwindigkeit her lohnt sich SSE, da ich anstatt 64 Schleifendurchgänge (FPU) nur 16 mit SSE brauche.

    Gruß, Nicky


Anmelden zum Antworten