Kompilierung / Assemblierung

  • Allgemein

Es gibt 19 Antworten in diesem Thema. Der letzte Beitrag () ist von ThePlexian.

    Kompilierung / Assemblierung

    Hey, ich hab da nochmla ne Frage:

    Ich habe jetzt meinen Quellcode, und möchte wissen was passiert, wenn eine EXE daraus entsteht.
    Meine jetzige Annahme sieht so aus:
    - Vorhanden: Quelltext einer Hochsprache
    - (Manchmal) Mittels Präprozessor wird der Quelltext optimiert (Entfernung von LZ + Komm. bspw.)
    - Mittels Compiler (Kompilierer) in eine Zwischensprache (meistens Assemblersprache)
    - Mittels Assembler (Assemblierer) in eine oder mehrere Objektdatei(en)
    - Mittels Linker zu einer ausführbaren Datei (.exe) und deren Komponenten (.dll)

    Stimmt das so ?

    Und wenn ja, warum ist ILSpy dann ein Decompiler und kein Disassembler ?

    *Topic verschoben*
    »There's no need to "teach" atheism. It's the natural result of education without indoctrination.« — Ricky Gervais

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Marcus Gräfe“ ()

    Das übernimmt der Just-In-Time Compiler. Dieser macht aus dem IL-Code dann schlussendlich richtigen Maschinencode. Deshalb starten .NET Anwendungen etwas langsamer.
    Jedoch tut sich in letzter Zeit recht viel bei Thema .NET Compiler. Vor kurzem wurde Roslyn auf codeplex veröffentlicht (open source). Zusätzlich läuft eine art Forschungsprojekt mit Namen .NET Native, welches man bereits für Store Apps ausprobieren kann. Hierbei gilt das alte Prinzip nicht mehr. Es wird bei z.B. C Maschinencode erstellt. Jedoch bleiben die Vorteile wie z.B. der GC (ja ich empfinde die automatische Speicherverwaltung als Vorteil!) erhalten. Daneben soll auch demnächst Unterstützung für SIMD Befehle kommen. Was ebenfalls ein enormer Fortschritt wäre (besonders für mich mit CSCore ;)).


    Opensource Audio-Bibliothek auf github: KLICK, im Showroom oder auf NuGet.
    Gilt diese Ausnahme nur für .Net und Java und sonst meine oben beschriebene Vorgehensweise ?

    EDIT: Ah, danke Trade :)
    »There's no need to "teach" atheism. It's the natural result of education without indoctrination.« — Ricky Gervais
    microsoft.com/germany/msdn/akt…008DasEntwicklerbuch.aspx

    Seite 53, genau beschrieben, was da abläuft. Wer das System nicht kennt, auf dem er programmiert, sollte es im Grunde sein lassen.
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o
    Nein es gibt noch mehrere Sprachen welche nicht direkt auf Maschinencode compilieren. Aber wer weiß. Vll. ist das bei .NET Sprachen schon bald Vergangenheit^^ (siehe Post von vorhin: Kompilierung / Assemblierung).


    Opensource Audio-Bibliothek auf github: KLICK, im Showroom oder auf NuGet.
    In 'ner nativen Anwendung läuft dass auch anders.
    1. Der Präprozessor guckt nach seinen Direktiven und betreibt fleißig Textersetzung.
    2. Der Interpreter "übersetzt" die neuen Quelldateien für den Compiler.
    3. Der Compiler übernimmt eventuelle Optimierungen (Performance und/oder Größe) und kompiliert für jede Datei eine "Objekt"-Datei (COFF)
    4. Der Resourcecompiler kompiliert aus RC-Script und Resourcen eine Datei.
    5. Dann schnürt der Linker alles zu einer PE, linkt zu allen externen PE's, fügt die Resourcen ein, setzt entsprechende Einstellungen in der PE und entscheidet dann das Target. Ob's eine GUI-, CUI-Anwendung, dynamische- oder statische Bibltiothek, oder etwas Eigenes sein darf.
    In der nativen Welt gibt es keinen großen Unterschied zwischen Dll oder Exe. Einzig der Einstiegspunkt und 1 Bit (dass gesetzt ist, oder nicht) entscheidet darüber. Man kann aus einer GUI/CUI-Anwendung genauso Funktionen exportieren, wie mit 'ner Dll.

    Gonger96 schrieb:

    In der nativen Welt gibt es keinen großen Unterschied zwischen Dll oder Exe.

    Was in der .NET Welt auch so ist.


    Opensource Audio-Bibliothek auf github: KLICK, im Showroom oder auf NuGet.
    @Gonger96 : In was übersetzt der Interpreter ?

    Und warum heißt es JIT-Compiler und nicht -Assembler ? Schließlich wird ja Assemblercode -> Maschinencode

    EDIT: Also gibt es gar keinen "einheitlichen" Vorgang sondern es variiert mit der Sprache... Gibt es wenigstens eine häufige Variante ?
    »There's no need to "teach" atheism. It's the natural result of education without indoctrination.« — Ricky Gervais
    Weil es ein Compiler ist. Da wird ja nicht aus Assembler(Sprache) Maschinencode, sondern aus IL wird Maschienencode. Assembler(Sprache) wäre ja das wirkliche Instructionset des Prozessors.IL ist eine assemblerartige Zwischensprache. Assembler(Programme) hast du in Hochsprachen nie, auch in Lowlevelsprachen nicht. Assembler(Programme) übersetzen deine Instructions einfach nur in die entsprechenden Bytes, die der Prozessor versteht. Assembler(Programme) braucht man nur in Assembler(Sprache). C, C++, C#, VB, VB.Net verwenden alle Compiler. Der Interpreter ist zu 99% im Compiler drin, der interpretiert einfach den Quellcode und macht die ganze Arbeit. Der Compiler selbst kompilliert das Fertige dann nur zur PE (COFF) oder in .Net direkt zur Exe/Dll.

    Bei nativen Sprachen ists fast immer so ähnlich wie ich es beschrieben habe. In .Net fällt der Linker und Resourcencompiler weg. Eine verwaltete PE (ist sogar im PE-Format selbst implementiert) linkt nur zur mscoree, mit dem entsprechenden Einstiegspunkt und so geht's dann über in die CLR.

    ThePlexian schrieb:

    EDIT: Ah, danke Trade

    Wofür? :D
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:

    thefiloe schrieb:

    Jedoch bleiben die Vorteile wie z.B. der GC (ja ich empfinde die automatische Speicherverwaltung als Vorteil!) erhalten.

    Soetwas sehe ich nicht unbedingt als Vorteil, sondern eher als Standard. Wer möchte noch irgendwelchen Speicher freigeben und löschen? Macht alles nur unnötig kompliziert. Ich halte aber IDisposeable für einen gewaltigen Designfehler. Man muss hier nämlich explizit Speicher freigeben. In anderen Sprachen wird sowas einfach im Destruktor gemacht und die Klasse kümmert sich selbst 'drum. Dann kann man frühzeitig den Speicher freigeben oder nicht wenn's einen nicht kümmert.
    Der Standard sieht vor, dass Dispose im Destruktor aufgerufen wird. ^^
    Dass die manuelle Variante als praktikabler angesehen wird, hängt vermutlich damit zusammen, dass man sich über das Freigeben von unverwaltetem Speicher bewusst sein sollte.
    Also so, zumindest bei den meisten Sprachen (.Net, C/C++ ?, Java):
    - Vorhanden: Quelltext einer Hochsprache
    - (Manchmal) Mittels Präprozessor wird der Quelltext optimiert (Entfernung von LZ + Komm. bspw.)
    - Mittels Interpreter wird der Code für den Compiler vorbereitet (Besser Erklärung)
    - Mittels Compiler (Kompilierer) in eine Zwischensprache (meistens assemblerähnlige Sprache)
    - Mittels Linker zu einer ausführbaren Datei (.exe) und deren Komponenten (.dll)

    -Programmstart: Mit einem JIT-Compiler von der Zwischensprache in Maschinensprache, während der Laufzeit.
    --> Keine Performanceeinbüßungen, da erstens immer nur die aktuelle Methode kompiliert wird, und außerdem sich der JIT-Compiler Wissen über die CPU holen kann, und den Code dementsprechend individuell optimieren kann.

    Richtig ?


    EDIT: Oh sry @Trade , ich meinte @thefiloe (danke!), ich hatte nur das grüne Icon gesehen und dachte an dich ^^
    »There's no need to "teach" atheism. It's the natural result of education without indoctrination.« — Ricky Gervais
    In .Net gibts nur einen Finalizer für das Freigeben von unverwalteten Ressourcen. Im Finalizer wird dann Dispose() aufgerufen. Hätte man den Finalizer etwas anders gestaltet, wäre IDisposeable garnicht nötig.

    Der Präprozessor optimiert Garnichts. Der macht reine Textersetzung. Der Compiler konpiliert nur in .Net zu IL, in Nativ wird direkt Maschinencode abgepackt in Coff's.

    Gonger96 schrieb:

    Ich halte aber IDisposeable für einen gewaltigen Designfehler. Man muss hier nämlich explizit Speicher freigeben.

    Nein ist es nicht. a) Musst du nur nicht verwalteten Speicher freigeben und b) gibt es dafür keine guten Alternativen die auf jede Situation anwendbar sind. Die Runtime kann nicht wissen wo im nicht verwalteten Bereich Speicher reserviert wird. Deshalb ja auch ... nicht verwaltet. Finde das auch nicht gerade schön aber das hat man davon, wenn man alte Sprachen wie C und C++ mitschleppt.

    Gonger96 schrieb:

    Hätte man den Finalizer etwas anders gestaltet, wäre IDisposeable garnicht nötig.

    Ob es dann ein interface ist oder ich das sonst irgendwie ausprogrammieren muss... sei dahin gestellt. Tatsache ist aber, dass die korrekte IDisposeable Implementierung vorsieht, dass sowohl verwaltete als auch nicht nicht verwaltete Ressourcen freigegeben werden sollen. Bei den verwalteten handelt es sich z.B. darum, dass du bei Netzwerkkommunikation dich noch dem Protokoll entsprechend verabschiedest. Bei nicht verwalteten musste dann halt noch eventuelle Handles,... freigeben. Das zu trennen wäre aber ebenfalls Unfug. Je nach Situation muss eine gewisse Reihenfolge beim Freigeben eingehalten werden.

    ThePlexian schrieb:

    Also haben Native Sprachen auch keinen JIT-Compiler ?

    Wenn eine Sprache direkt in Maschinencode übersetzt wird, braucht es keinen JIT-Compiler. Wenn eine Sprache in einen Pseudo-Asm übersetzt wird, welcher als Zwischenstufe dient, braucht es einen JIT-Compiler. Wenn gar nix übersetzt wird und einfach nur roher Code vorliegt, braucht es einen Interpreter. Was ist daran so kompliziert?
    Und wie gesagt: Präprozessor ist grob gesagt dafür zuständig den Code selbst vorzubereiten. Sagen wir du hast nen Makro, dann wird überall das Makro eingesetzt. Hast du etwas durch etwas wie z.B. #if ABC ausgeschlossen, so wird der entsprechende Code entfernt,...


    Opensource Audio-Bibliothek auf github: KLICK, im Showroom oder auf NuGet.