Someone: Wie ist das noch gleich mit den Computern? *g*

Hallo erstmal.

Ich sitz da grad mit wem und wir sehen uns nen FIlm den wir runtergeladen haben an (Hackers).
Wie dam auch sei, wir beginnehn zu quatschen und wieder mal stellt sich die Frage:
Wie funktioniert das mit den PCs genau?
Wenn man beispielsweise ein C-Programm compiliert dann wird dass doch in Assembler Code umgewandelt, aber manb kann keinen klaren Code lsen. Wenn man Assembler schreibt muss man das ganze ja eigentlich auch wieder durch ein spezielles Assembler Programm laufen lassen, soweit ich weiß. (in was wird sowas eigentlich geschrieben!?)
Alsop Leute ich denk mal ihr versteht meine Frage jetz mmal so halbwegs und hoffe jemand kann das alles mal verständlich erklären *g*

Someone

  1. Hi,

    Wie funktioniert das mit den PCs genau?
    Wenn man beispielsweise ein C-Programm compiliert dann wird dass
    doch in Assembler Code umgewandelt, aber manb kann keinen klaren
    Code lesen.

    Nein, wenn man ein C-Programm compiliert, wird das umgewandelt in
    Maschienensprache ,) Und klar kann man klaren Code lesen, nur du
    und ich vielleicht nicht *g* aber frueher (70ger? weiss net mehr ,))
    war es grosse Mode, direkt in Maschinencode zu schreiben, z. B. mit
    dem DOS-Debugger.
    Der Maschinencode wird vom Betriebssystem in Prozessorbefehle
    umgewandelt und verarbeitet ,)

    Wenn man Assembler schreibt muss man das ganze ja
    eigentlich auch wieder durch ein spezielles Assembler Programm
    laufen lassen, soweit ich weiß. (in was wird sowas eigentlich
    geschrieben!?)

    Klar, Assembler ist zwar schon sehr nahe an Maschinencode, aber
    es ist eben noch nicht ganz Maschinencode.
    Der Assembler-Compiler wird wahrscheinlich wohl direkt in
    Maschinencode geschrieben sein ,)

    mfg
    CK1

    1. Nein, wenn man ein C-Programm compiliert, wird das umgewandelt in
      Maschienensprache ,)

      Das ist unterschiedlich. Es ist nicht unueblich, dass ein Compiler den C-Source in ein Assembler-Programm uebersetzt, das dann vom Assembler zu Maschinencode uebersetzt wird. Manche Compiler bauen aber auch direkt den Maschinencode zusammen.

      Der Maschinencode wird vom Betriebssystem in Prozessorbefehle
      umgewandelt und verarbeitet ,)

      Haeh?! Das ist jetzt wirklich Quatsch!
      Der Maschinencode wird vom Prozessor ausgefuehrt, Punkt. Da pfuscht kein Betriebssystem oder sonstwas drin rum. Das BS selbst ist ja schliesslich auch nur Maschinencode, nichts anderes als ein stinknormales Programm.

      Klar, Assembler ist zwar schon sehr nahe an Maschinencode, aber
      es ist eben noch nicht ganz Maschinencode.

      Es ist eine Abbildung der Zahlen, die der Prozessor als Instruktionen interpretieren kann, in eine etwas lesbarere Form. Z.B. entspricht auf einem Intel-Prozessor (die normalen in PC eingesetzten meine ich) die Byte-Sequenz
      B8 34 12
      dem Assemblerbefehl mov ax, 1234h
      der die Konstante 1234h (hexadezimal) in das AX-Register laedt.

      Da tendenziell jeder Prozessor andere Instruktionen versteht, ist auch der Assembler fuer jeden Prozessor ein anderer.

      Der Assembler-Compiler wird wahrscheinlich wohl direkt in
      Maschinencode geschrieben sein ,)

      Der Assembler-Compiler heisst einfach Assembler, und wird heutzutage sicher nicht mehr in Maschinensprache geschrieben, sondern in einer hoeheren Programmiersprache, fuer die es schon einen Compiler gibt. Tja wie war das mit der Henne und dem Ei, irgendwann musste da wohl mal ein erster Assembler sein. Keine Ahnung, wo der herkam. ;-)

      So lange

      1. Hi,

        Das ist unterschiedlich. Es ist nicht unueblich, dass ein
        Compiler den C-Source in ein Assembler-Programm uebersetzt, das
        dann vom Assembler zu Maschinencode uebersetzt wird. Manche
        Compiler bauen aber auch direkt den Maschinencode zusammen.

        Sorry, ich hab bis jetzt nur gehoert, dass die Compiler den direkt in
        Maschinencode uebersetzen.

        Haeh?! Das ist jetzt wirklich Quatsch!
        Der Maschinencode wird vom Prozessor ausgefuehrt, Punkt. Da
        pfuscht kein Betriebssystem oder sonstwas drin rum. Das BS selbst
        ist ja schliesslich auch nur Maschinencode, nichts anderes als
        ein stinknormales Programm.

        hm, tut mir leid, ich hab das anders gelernt... oder ich werf da was
        durcheinander *g*

        Der Assembler-Compiler heisst einfach Assembler, und wird
        heutzutage sicher nicht mehr in Maschinensprache geschrieben,
        sondern in einer hoeheren Programmiersprache, fuer die es schon
        einen Compiler gibt. Tja wie war das mit der Henne und dem Ei,
        irgendwann musste da wohl mal ein erster Assembler sein. Keine
        Ahnung, wo der herkam. ;-)

        Von dem ersten Compiler hab ich geredet.. der wird wohl in
        Maschinencode geschrieben worden sein, zumindest hoert sich das
        logisch fuer mich an *g*

        mfg
        CK1

        1. hi!

          Haeh?! Das ist jetzt wirklich Quatsch!
          Der Maschinencode wird vom Prozessor ausgefuehrt, Punkt. Da
          pfuscht kein Betriebssystem oder sonstwas drin rum. Das BS selbst
          ist ja schliesslich auch nur Maschinencode, nichts anderes als
          ein stinknormales Programm.
          hm, tut mir leid, ich hab das anders gelernt... oder ich werf da was
          durcheinander *g*

          In welcher Hinsicht? Die ausführbare Datei eines Programs enthält reinen Maschinencode, der direkt vom
          Prozessor ausgeführt wird. Gib zb. mal "debug programm.exe" ein und dann "u".

          === cut ===
          0CB3:0100 50            PUSH    AX
          0CB3:0101 4B            DEC     BX
          0CB3:0102 0304          ADD     AX,[SI]
          0CB3:0104 1400          ADC     AL,00
          0CB3:0106 0000          ADD     [BX+SI],AL
          0CB3:0108 0800          OR      [BX+SI],AL
          0CB3:010A 046A          ADD     AL,6A
          0CB3:010C 7B26          JPO     0134
          0CB3:010E F718          NEG     WORD PTR [BX+SI]
          0CB3:0110 D98C49020000  ESC     09,[SI+0249][SI+0000]
          0CB3:0116 1E            PUSH    DS
          0CB3:0117 0400          ADD     AL,00
          0CB3:0119 000A          ADD     [BP+SI],CL
          0CB3:011B 0000          ADD     [BX+SI],AL
          0CB3:011D 005265        ADD     [BP+SI+65],DL
          === cut ===
          Vornedran steht die Adresse der jeweiligen Stelle im Programm (xxxx:0100 ist normalerweise die erste
          Anweisung), danach kommt der Maschinencode in Hex-Form, danach des disassemblierte Sourcecode
          (Disassemblierung des Sourcecodes ist jederzeit möglich, da - wie Calocybe schon schrieb - jeder
          ASM-Befehl einen festen Maschinencode hat).

          Um eine EXE-Datei auszuführen (bzw. eigentlich jedes Programm unter irgendeinem OS) lädt das
          Betriebssystem, also der Kernel, das Programm in den Speicher und übergibt dem Prozessor die
          Speicheradresse der ersten Maschinencode-Anweisung. Der Prozessor beginnt dann an dieser Stelle
          und arbeitet die Maschinencodes nach und nach ab, bis er auf eine Anweisung trifft, die diese Abarbeitung
          beendet (hm, ein einfacher Interrupt schätze ich, kann mich aber auch irren).

          Das Betriebssystem tut also überhaupt nichts weiteres, um dem Prozessor irgendwie den Maschinencode
          zur Verfügung zu stellen oder nochmal zu interpretieren und dann entsprechende Prozessor-Befehle
          auszuführen.

          bye, Frank!

          ps. Das ist alles schon relativ lange her. Schlagt mich nicht, wenn ich jetzt teilweise Müll erzählt habe ;)

          1. hi!

            Vielleicht noch ein paar Ergänzungen :)

            Ein paar ASM-befehle dürfte ich vom Sinn her noch hinkriegen ;)

            0CB3:0100 50            PUSH    AX

            Das stellt woh lden Wert des Registers AX wieder her, der vorher auf dem Stack gespeichert wurde.

            0CB3:0101 4B            DEC     BX

            BX um 1 verringern.

            0CB3:0102 0304          ADD     AX,[SI]

            SI zu AX addieren.

            Den Rest kenne ich dann eher nicht ;) Falls sich jemand dafür interessiert, hier gibt es eine Liste für die
            x86-Prozessoren von Intel: http://www.penguin.cz/~literakl/intel/intel.html

            So gut kenne ich mich mit ASM dann aber doch nicht aus. Das einzige, was ich zur Zeit wohl noch
            hinkriegen dürfte, sind ein paar Interrupts mit den passenden Registerwerten. Unter Windows und den
            meisten neueren Betriebssystemen dürfte das aber größtenteils relativ sinnlos sein :)

            bye, Frank!

            ps. Das ist alles schon relativ lange her. Schlagt mich nicht, wenn ich jetzt teilweise Müll erzählt habe ;)

            1. Hi Frank,

              0CB3:0102 0304          ADD     AX,[SI]
              SI zu AX addieren.

              Sorry, aber das bedeutet den Inhalt der Adresse, auf die SI zeigt, zu AX addieren. Ich glaube da wird implizit DS benutzt, aber sicher bin ich mir nicht. Bei den ganzen Adressierungsarten der Intel-Prozessoren bin ich nie komplett durchgestiegen.

              Wie du geschrieben hast, ist lange her. Irgendwo liegt auch noch mein altes Berichtsheft rum, da ist eine Assembler-Routine drin, die in QuickBASIC eingebunden werden kann, um eine Linie auf einer EGA-Karte im "hochauflösenden" Grafik-Modus (640x350) zu malen.

              Gruß,
              Martin

          2. Hi Frank,

            na dann will ich mal für noch mehr Verwirrung sorgen <g>

            Um eine EXE-Datei auszuführen (bzw. eigentlich jedes Programm unter irgendeinem OS) lädt das
            Betriebssystem, also der Kernel,

            dieser Teil vom kernel wird als Loader bezeichnet.

            das Programm in den Speicher und übergibt dem Prozessor die
            Speicheradresse der ersten Maschinencode-Anweisung.

            Bei modernen Betriebssystemen nicht ganz. Zuerst werden die externen Referenzen (Sprungziele in DLLs) aufgelöst, das Code-Segment auf execute-only gesetzt, und ein paar Sachen mehr, mit denen ich mich nie beschäftigen musste. Ältere Betriebssysteme hatten einfach einen Jump oder Call auf die Einsprungadresse.

            Der Prozessor beginnt dann an dieser Stelle
            und arbeitet die Maschinencodes nach und nach ab, bis er auf eine Anweisung trifft, die diese Abarbeitung
            beendet (hm, ein einfacher Interrupt schätze ich, kann mich aber auch irren).

            Das müsste ich mal debuggen um genau zu sein, aber ich denke, dem Betriebssystem wird einfach mitgeteilt dass das Programm jetzt fertig ist, durch einen Betriebssystemaufruf.

            Das Betriebssystem tut also überhaupt nichts weiteres, um dem Prozessor irgendwie den Maschinencode
            zur Verfügung zu stellen oder nochmal zu interpretieren und dann entsprechende Prozessor-Befehle
            auszuführen.

            ps. Das ist alles schon relativ lange her. Schlagt mich nicht, wenn ich jetzt teilweise Müll erzählt habe ;)

            Nicht nur bei dir. Fehlt zur ursprünglichen Frage nur noch dass ein C/C++-Compiler heutzutage auch in C geschrieben ist.

            Gruß,
            Martin

            1. hi!

              das Programm in den Speicher und übergibt dem Prozessor die
              Speicheradresse der ersten Maschinencode-Anweisung.
              Bei modernen Betriebssystemen nicht ganz. Zuerst werden die externen Referenzen (Sprungziele in
              DLLs) aufgelöst, das Code-Segment auf execute-only gesetzt, und ein paar Sachen mehr, mit denen
              ich mich nie beschäftigen musste.

              Ok, kann sein. Das letzte mal, dass ich was mit ASM zu tun hatte, war unter MS-DOS ;)

              Ältere Betriebssysteme hatten einfach einen Jump oder Call auf die Einsprungadresse.

              So konnte man übrigens in QuickBasic INLINE-Code ausführen: den Code in eine Variable schreiben und
              die Adresse der Variablen anspringen :) Habe ich zwar nie selbst ausprobiert, soll aber angeblich
              funktionieren.

              Der Prozessor beginnt dann an dieser Stelle
              und arbeitet die Maschinencodes nach und nach ab, bis er auf eine Anweisung trifft, die diese Abarbeitung
              beendet (hm, ein einfacher Interrupt schätze ich, kann mich aber auch irren).
              Das müsste ich mal debuggen um genau zu sein, aber ich denke, dem Betriebssystem wird einfach
              mitgeteilt dass das Programm jetzt fertig ist, durch einen Betriebssystemaufruf.

              Schau dir mal eine der kleinen .com-Dateien im Windows-Verzeichnis an (zb. chcp.com oder loadfix.com
              unter W2K). Die sind überblickbar. Kann es sein, dass man unter DOS eine INT21-Funktion aufrufen
              musste? Das ist alles schon so lange her... ;)

              bye, Frank!

              1. Hi Frank,

                Ok, kann sein. Das letzte mal, dass ich was mit ASM zu tun hatte, war unter MS-DOS ;)

                ich auch ;-) Aber man liest sich durch so Einiges.

                So konnte man übrigens in QuickBasic INLINE-Code ausführen: den Code in eine Variable schreiben und
                die Adresse der Variablen anspringen :) Habe ich zwar nie selbst ausprobiert, soll aber angeblich
                funktionieren.

                Stimmt, das geht. Hab' ich zwar nie in QuickBASIC gemacht, aber in Turbo Pascal 4/5/6. Ich hab da in Assembler selbstgeschriebene Hardcopyroutinen geladen, die zum Auslesen des Bildschirminhaltes in die Turbo Pascal-Runtime gesprungen sind. Man hat halt so einige Sauereien gemacht <g>

                Kann es sein, dass man unter DOS eine INT21-Funktion aufrufen
                musste? Das ist alles schon so lange her... ;)

                <nachguck> Entweder 0x00 in AH (DOS vor V2) oder 0x4c und in AL den Exitcode. Braucht jemand noch ein Buch "DOS 5 für Programmierer"?

                Irgendwie fühl ich mich auf einmal so alt.

                Gruß,
                Martin

        2. Moin,

          Sorry, ich hab bis jetzt nur gehoert, dass die Compiler den direkt in
          Maschinencode uebersetzen.

          Eines der prominentesten Gegenbeispiele ist wohl
          gcc bzw. g++.  
          Es gibt da noch ganz andere Variationen, z.B. erzeugt "g77" aus
          einem FORTRAN Programm C-Code, der dann wiederum an
          gcc übergeben wird, um schließlich als Assembler-Source von
          "as" in ein Objekt-File umgewandelt zu werden.

          Haeh?! Das ist jetzt wirklich Quatsch!
          Der Maschinencode wird vom Prozessor ausgefuehrt, Punkt. Da
          pfuscht kein Betriebssystem oder sonstwas drin rum. Das BS selbst
          ist ja schliesslich auch nur Maschinencode, nichts anderes als
          ein stinknormales Programm.

          hm, tut mir leid, ich hab das anders gelernt... oder ich werf da was
          durcheinander *g*

          Zu ergänzen ist an dieser Stelle vielleicht noch, daß in einem
          Maschinenprogramm absolute Sprungadressen auftreten können.
          Da der Speicherbereich des Programms bei jedem Aufruf
          verschieden sein kann, müssen diese Sprungadressen
          entsprechend angepaßt werden, was in der Tat eine Aufgabe
          des Betriebssystems ist (man nennt diesen Vorgang
          dann imho 'relozieren').
          Die Art, wie und wo diese Sprungadressen im Binärfile
          abgelegt sind usw. unterscheidet sich je nach Betriebssystem.

          Von dem ersten Compiler hab ich geredet.. der wird wohl in
          Maschinencode geschrieben worden sein, zumindest hoert sich das
          logisch fuer mich an *g*

          Wird wohl sein - ich denke jedenfalls nicht, daß der erste
          C-Compiler in Basic geschrieben wurde ;-)
          Danach geht es munter die Abstraktionsleiter aufwärts.
          So ist z.B. sowohl gcc als auch g++ selbst in C geschrieben.
          gcc benötigt also erstmal einen "anderen" C-Compiler, um
          selber zu funktionieren. Dafür kann gcc sich dann im zweiten
          Durchgang selbst optimieren...

          Bis dannundwann

          Andreas

  2. Hallo irgendwer ;-)

    Wenn man beispielsweise ein C-Programm compiliert dann wird dass doch in Assembler Code umgewandelt, aber manb kann keinen klaren Code lsen. Wenn man Assembler schreibt muss man das ganze ja eigentlich auch wieder durch ein spezielles Assembler Programm laufen lassen, soweit ich weiß. (in was wird sowas eigentlich geschrieben!?)
    Alsop Leute ich denk mal ihr versteht meine Frage jetz mmal so halbwegs und hoffe jemand kann das alles mal verständlich erklären *g*

    Mit dem C-Compiler wird ein C-Programm direkt in Maschinencode umgewandelt. Dieser ist eine Bytefolge, die den Instruktionen für den Prozessor entsprechen.
    Ein Assembler-Code hingegen ist ein Programm, dass aus kurzen, den Prozessorinstruktionen direkt enstprechenden Befehlen, besteht.
    Weiter beziehtsich das Assembler-Programm mit Registerzugriffen direkt auf die Hardware-Gegebenheiten der spezifischen Maschine.
    Darum werden Assembler-Programme auch gerne als "maschinennah" bezeichnet.

    Ich hoffe, das klärt Dir den Sachverhalt etwas auf.

    Grüsse
    Tom

  3. Wenn man beispielsweise ein C-Programm compiliert
    dann wird dass doch in Assembler Code umgewandelt,
    aber manb kann keinen klaren Code lsen. Wenn man
    Assembler schreibt muss man das ganze ja eigentlich
    auch wieder durch ein spezielles Assembler Programm
    laufen lassen, soweit ich weiß. (in was wird sowas
    eigentlich geschrieben!?)

    Nachdem Calocybe und Frank Schönmann die wesentlichen
    Antworten bereits gegeben haben, möchte ich noch etwas
    nachtragen zum Thema Assembler und Maschinensprache.
    Beide sind für mich nämlich wesentlich weiter voneinan-
    der entfernt, als die bisherigen Beiträge dies vermuten
    lassen. (Das hängt nicht zuletzt mit der Qualität der
    verschiedenen Assembler zusammen.)

    Maschinensprache besteht also aus Bytefolgen.
    Üblicherweise beginnt eine solche Bytefolge mit einer
    Kennzeichnung des Befehls (Beispiele siehe bei Frank);
    aus dieser Kennzeichnung ist dann auch ableitbar, wie
    viele Bytes der Befehl enthält (das ist nämlich sehr
    unterschiedlich, weil es vom Befehl abhängt, welche und
    wie viele Operanden er verarbeiten soll und in welchem
    Format die anzugeben sind: Will man den Inhalt zweier
    Register addieren, dann reichen eine ADD-Markierung und
    die Registernummern; will man zwei Speicherwerte addieren

    • vorausgesetzt, die CPU kann so etwas - dann müssen zwei
      Speicheradressen als Operanden her, und die sind dann
      etwas länger usw.).
      Man "denkt" also wirklich in Speicherabbildern und
      (numerischen) Adressen, wenn man Maschinensprache
      schreibt. Das tat allerdings auch in den 70er-Jahren
      schon niemand mehr.

    Assembler ist eine Sprache, die versucht, diese Maschi-
    nensprache durch abstrakte Features handhabbarer zu
    machen. Beispielsweise will man eben möglichst *nicht*
    wissen müssen, wie lang ein Befehl ist - denn versuche
    mal, eine Schleife zu programmieren, wenn Du die Sprung-
    adressen in realen Speicherpositionen berechnen mußt!
    Füge nur einen einzigen Befehl in Dein Programm ein,
    und alle Adressen sind falsch, nämlich um die Länge
    dieses Befehls verschoben.
    Also versteht Assembler als allererstes schon mal Varia-
    blen. So, wie es Befehle in Assembler gibt, mit denen
    man Maschinenoperationen notiert, gibt es auch Befehle,
    mit denen man Variablen deklariert - ganz ähnlich wie
    in JavaScript, bloß beschreibt die Anweisungsfolge (im
    Wesentlichen) immer noch sequentiell eine Speicherbele-
    gung. Wenn man also mitten zwischen seinen Befehlen
    eine Variable deklariert, ist das wahrscheinlich keine
    so brilliante Idee - aber ausschließen kann man das
    auch nicht.
    Und wenn man Speicherstellen einen Variablennamen geben
    kann, dann natürlich auch Programmstellen einen Sprung-
    markennamen. Der Assembler macht für den Entwickler die
    gesamte Adreßrechnerei und generiert am Ende (fast schon
    Maschinenbefehle mit den entsprechenden Operandenwerten
    (Ich überspringe mal den Aspekt der Relozierbarkeit,
    Linker usw. - das fällt dann ins Kapitel Betriebssystem-
    architektur.)

    Das nächste, was man auch dringend braucht, ist die
    Möglichkeit, Code innerhalb eines Programms wiederzu-
    verwenden. Also das, wofür man heute Funktionen schreibt.
    Dafür gibt es in Assembler zwei Möglichkeiten:

    • Entweder springt man an den Anfang eines Code-Stücks,
        nachdem man seine aktuelle Adresse vorher irgendwo
        hinterlegt hat, und das Code-Stück springt am Ende
        wieder dorthin (plus eine Befehlslänge) zurück,
    • oder man läßt den Code einfach kopieren.
        Dafür gibt es in Assembler Makros - ja, das Zeug, was
        es auch in Word oder Excel gibt, die Idee ist *ur*alt.
        Ein wirklich guter Assembler kann bei solchen Makros
        übrigens auch Parameter übergeben und in einer Meta-
        sprache Programme formulieren, die zur Assemblierungs-
        zeit bestimmen, wie der Inhalt der generierten Befehle
        aussehen soll - man kann also durchaus variablen Code
        damit erzeugen.

    Zudem kann man natürlich beliebige Assembler-Module
    separat schreiben und übersetzen, und erst später zu
    einem Programm zusammenbinden lassen. Modularität ist
    keine Erfindung der neueren Informatikgeschichte.

    Die Vielzahl weiterer features eines guten Assemblers
    (Dummy-Sections und Basisregister, für etwas Ähnliches
    wie Objektadressierung) aufzuzählen würde zu weit führen.
    Was ich damit letztlich nur sagen wollte, ist: Auch
    wenn heute niemand mehr maschinenabhängig programmiert,
    so finden sich doch fast *alle* wesentlichen features
    von 3GL-Programmiersprachen bereits in Assemblersprachen
    der 70er Jahre wieder.

    Die uralte IBM370-Architektur, also der gute alte Groß-
    rechner, hat einen (!) Maschinenbefehl, der
    1. den Inhalt einer Menge (!) von Registern an eine
       Speicherstelle schreibt, deren Adresse in einem als
       Operand anzugebenden Register steht,
    2. die aktuelle Adresse plus seine Befehlslänge in ein
       Register schreibt und
    3. an die in einem anderen Register oder als Operand im
       Speicher stehende Adresse springt.
    Allein mit diesen einzigen Befehl hat man schon eine
    wunderbare Prozeduraufrufschnittstelle, mehr braucht
    man nicht. (Rückladen einer Registermenge gibt es
    natürlich auch, das macht dann die aufgerufene Funktion
    direkt vor dem Rücksprung.)
    Und die Zieladresse kann man dann auch noch mit symbo-
    lischen Adressen (quasi dem "Funktionsnamen") angeben.
    Wenn man solche Speicherbereiche im Speicher "stapelt",
    dann hat man auch (fast) alle Voraussetzungen für ge-
    schachtelte, insbesondere rekursive Funktionsaufrufe.

    Ein gutes, strukturiert geschriebenes Assemblerprogramm
    ist genauso lesbar wie ein Programm in einer beliebigen
    "Hochsprache". Es ist nur länger, weil man Sprachelemente
    wie Schleifen oder Case-Abfragen eben selbst programmieren
    muß. Das aber wiederum ist eine Eigenschaft der zugrunde-
    liegenden Maschinensprache - nicht des Assemblers ...

    Und die Maschinensprachen der Großrechner konnten halt
    schon vor 30 Jahren Dinge, die ein Pentium heute noch
    nicht beherrscht (aber heute auch nicht mehr beherrschen
    muß, weil es eben Hochsprachen gibt). Beispielsweise
    mit *einem* Maschinenbefehl zwei 16 Millionen Zeichen
    lange Strings miteinander zu vergleichen und die Position
    der ersten Abweichung in einem Register hinterlegen ...