Optimierung: Was macht der Compiler hier?



  • Das ist ja jetzt die Frage, ich nehme an, C. M. Obrecht programmiert unter Visual Studio, hat man denn da ein Tool, mit dem man unbeschwert in die Objektdateien reinschauen kann? Ähnlich objdump in binutils (das ist dieses GNU Zeugs, in Anlehnung an die Diskussion hier http://www.c-plusplus.net/forum/viewtopic-var-t-is-230238.html (Assembler - Wie anfangen?) )?



  • abc.w schrieb:

    Das ist ja jetzt die Frage, ich nehme an, C. M. Obrecht programmiert unter Visual Studio, hat man denn da ein Tool, mit dem man unbeschwert in die Objektdateien reinschauen kann? Ähnlich objdump ...?

    In Visual Studio Debuggen starten, bis zu einem Haltepunkt oder im Enzelschritt
    debuggen - rechte Maustaste = Menü - Gehe zu Dissasembly klicken - und
    der Assemblercode wird angezeigt. 😞



  • Noch besser: In Visual Studio kannst du dir ein Assembler Listing ausgeben lassen + Kommentare auf welche Codezeilen sich der Assembler-Code jeweils bezieht. Das ist besser als irgendiwe zu disassemblieren und dann den Code zu suchen.

    Gruß
    Don06



  • abc.w:
    Herrje, nimm bitte zur Kenntnis, dass es neben den Gnu-Tools auch noch sehr brauchbare Alternativen gibt.
    Ich habe zwar von Linux-Anbetern schon oefter das Geruecht gehoert, mit Microsoft-Tools koenne man nicht entwickeln, aber so schlecht sind die nun auch wieder nicht.
    Natuerlich enthaelt das VS wie jede halbwegs ernstzunehmende Entwicklungsumgebung oder Toolchain auch einen Debugger mit ausgefeiltem Disassembler.
    Den kann man sogar intuitiv und uebersichtlich per Maus bedienen, ohne sich erstmal durch 100te Zeilen frickelige Konsolenkommandos zu wuehlen oder mit einzelnen obj-Dateien auseinandersetzen zu muessen.
    Weiss allerdings nicht, ob der auch in allen Versionen verfuegbar ist.
    Aber selbst wenn nicht, gibt es noch genug Alternativen zum Disassemblieren/Debuggen unter Windows, von denen die binutils fuer jemanden, der sonst nicht auch mit Gnu arbeitet, eher eine schlechte Wahl sind.



  • Schon gut, schon gut, bin ja dabei, die IDE kennenzulernen...



  • Und übrigens, C. M. Obrecht hat ja nicht erwähnt, dass er bereits ein lauffähiges Programm hat, ein Programm, das er im Debugger von VS laden könnte... Vielleicht hat er eben nur diese eine Datei als Modul kompiliert. Was macht er denn nun? Er, und vor allem ich, möchten nun gerne wissen, was hat der Compiler denn da gemacht in der Objektdatei?



  • Du kannst dir AFAIK im VS alles disassemblieren lassen, so lange es compiliert. Dazu brauchst du kein komplettes Programm.
    Falls du weitere Fragen zur Benutzung von VS hast, mach bitte in den entsprechenden Foren neue Threads auf. Ansonsten hast du ja schon einen Thread zum Thema Alternativen zu Gnu, bleib doch bitte mit dem Thema dort.



  • Das hat ja nun eine Diskussion ausgelöst 😃 Das mit dem Haltepunkt setzen wäre eine Idee, werde dann über das Resultat berichten. Im Disassembly mit einem externen Disassembler fand ich (bei optimiertem Code ohnehin) kaum je meinen eigenen Code wieder, daher ist das eine Idee; bin ich noch nicht drauf gekommen.

    EDIT: Hier das Resultat:

    register DWORD dwPos=(DWORD)atoi(spos);
    004F7689  lea         eax,[spos] 
    004F768F  push        eax  
    004F7690  call        @ILT+41830(_atoi) (4E036Bh) 
    004F7695  add         esp,4 
    004F7698  mov         dword ptr [dwPos],eax 
    
    __asm{
    		mov eax, dwPos 
    004F769E  mov         eax,dword ptr [dwPos] 
      mov ecx, 1000 
    004F76A4  mov         ecx,3E8h 
      mov ebx, 60 
    004F76A9  mov         ebx,3Ch 
      Xor edx, edx
    

    und in der Release-Version:

    __asm{
    		mov eax, dwPos 
    00431248  mov         eax,dword ptr [esp+18h] 
      mov ecx, 1000 
    0043124C  mov         ecx,3E8h 
      mov ebx, 60 
    00431251  mov         ebx,3Ch 
      Xor edx, edx
    

    Also die Register-Anweisung wird definitiv ignoriert.

    Ja, ich verwende Visual Studio 2005, mit MFC, und das Programm ist lauffähig.
    Zum Cast

    DWORD dwPos=(DWORD)atoi(spos);
    

    nehme ich mal an da ein int sowieso ein DWORD ist wird kein zusätzlicher Code erzeugt, ist dieser Cast nur um den Compiler zu befriedigen?



  • Wahrscheinlich. Das hast du bei C-artigen Sprachen sehr oft, dass casts praktisch gar nichts bewirken, ausser Warnings beim compilieren zu vermeiden.



  • Der Code sieht jedenfalls auch ganz danach aus. Ausser bei Cast von int zu String und umgekehrt etc. natürlich. Hoffentlich auch, gäbe ja einigen zusätzlichen Code, bei den vielen Casts welche manchmal nötig sind.



  • mov eax,dword ptr [esp+18h]
      mov ecx,3E8h
      mov ebx,3Ch
    

    Also die Register-Anweisung wird definitiv ignoriert.

    Die Sache ist die, dass Dein Assembler-Code 1:1 vom Compiler uebernommen wird und dabei kein Versuch unternommen wird, diesen sinnvoll in den bestehenden Code einzubetten.
    Da Du fuer den Inline-Assembler eax (scheinbar) aus einer Variablen laedst, stellt der Compiler zuvor sicher, dass da auch der entsprechende Wert drin zu finden ist; das laesst sich mit der Register-Anweisung eben nicht vereinbaren.
    Eine Alternative waere eventuell den Return-Wert von atoi in eax zu erwarten.



  • hellihjb schrieb:

    Die Sache ist die, dass Dein Assembler-Code 1:1 vom Compiler uebernommen wird und dabei kein Versuch unternommen wird, diesen sinnvoll in den bestehenden Code einzubetten.

    Wahrscheinlich eher im Gegenteil; der Assemblerblock dürfte den Optimierer gewaltig ausbremsen.



  • Wahrscheinlich eher im Gegenteil

    Genau genommen ist es genau so wie ich schrieb; fuehrt in letzter Instanz aber auch zu Deiner Schlussfolgerung.



  • Ja, so meinte ich das auch, sorry. Das Gegenteil war auf den Versuch der sinnvollen Einbettung gemünzt.



  • gibt es auch schon compiler, die eigenen assemblercode auf wunsch auch optimieren? (wenn man nur z.b. rol/ror oder so verwenden will, aber dazu noch mov davor/dahinter einbaut, dass diese dann wegoptimiert werden)



  • Beim GCC kann man dem Inline-Assembler mitteilen, in welchen Registern Variablen und Returnwert angenommen werden sollen, genauso bei Open Watcom.
    Der eigentliche Code wird aber auch da nicht angefasst, sonst koennte man es ja auch gleich als C/C++ formulieren.



  • Das hab ich fast angenommen, dass da der Assemblercode Vorrang hat gegenüber der Register-Anweisung.
    Auf das Laden der Variable kommt es auch nicht wirklich an, aber wie würde das gehen den Rückgabewert von atoi direkt im eax zu haben? 😕

    Die ganze Berechnung in asm hätte in C auch nicht viel ausgemacht, aber vielleicht ist's etwas schneller falls C++ den Coprozessor verwenden würde. Wäre auch noch interessant ob der Compiler den Code auf den Wertebereich und Fliesskommazahlen prüft und dann je nach dem die CPU oder FPU benützt.



  • vielleicht ist's etwas schneller falls C++ den Coprozessor verwenden würde

    FPU fuer atoi ?

    wie würde das gehen den Rückgabewert von atoi direkt im eax zu haben

    Integer-Returnwerte werden immer in eax angenommen:

    int res;
       atoi("-12345");
       _asm {
          mov res,eax
       }
       printf("%d \n", res);
    

    Aber nach dem Aufruf einer Funktion (teuer) und dem Parsen eines Strings (noch teurer) kannst Du mit so'm Integer eigentlich nicht mehr viel anstellen dass irgendwie performancerelevant waere...
    Was hast Du denn ueberhaupt vor?



  • Nein nicht für atoi die FPU sondern die Berechnung (Umrechnung von Sekunden) die danach kommt, welche ich in Assembler geschrieben habe. Und ob dafür die FPU genommen würde, das wäre sicherlich langsamer mit allem drum und dran (die Methode wird 2 Mal in der Sekunde ausgeführt).

    Es kommt eigentlich nicht so drauf an, 2 Mal in der Sekunde ist ja nicht soo viel aber ich dachte ich schreibe das mal in Assembler, so einfach wie möglich schadet sicher nicht 🙂
    Ah ja klar wie Windows-Funktionen ebenfalls unter Assembler den Wert in EAX zurückgeben.



  • die "register" anweisung wird übrigens inzwischen von so gut wie allen vompilern komplett ignoriert - ob mit inline-asm oder ohne.


Anmelden zum Antworten