Eine Maschinensprache, wie sie bei Maschinencode bzw. nativem Code verwendet wird, ist eine Programmiersprache, bei der die Instruktionen, die vom Prozessor ausgeführt werden sollen, als formale Sprachelemente festgelegt sind. Aufgrund ihrer Nähe zur Hardware wird sie auch verallgemeinernd als die „Programmiersprache eines Computers“ bezeichnet.Duden Informatik. ISBN 3-411-05232-5. Umfang und Syntax der Maschinenbefehle sind im Befehlssatz definiert und abhängig vom Prozessortyp. Maschinensprache wird meistens als Binärcode oder vereinfacht mithilfe von Hexadezimalzahlen dargestellt.

Ein Maschinenbefehl ist hierbei eine Anweisung an den Prozessor, eine Operation durchzuführen, beispielsweise eine Addition oder einen Wertevergleich. Jede funktionelle Leistung eines Prozessors ist daher Ergebnis der Ausführung von Maschinencode, eines in Maschinensprache vorliegenden Programms.

Programme in Maschinensprache werden üblicherweise nicht vom Programmierer direkt erzeugt, sondern unter Nutzung einer höheren Programmiersprache oder einer Assemblersprache, wobei erst mithilfe eines Compilers bzw. Assemblers ausführbarer Maschinencode entsteht. Wird von „Programmierung in Maschinensprache“ gesprochen, ist damit manchmal fälschlicherweise die Programmierung in Assemblersprache gemeint. Bei der Ausführung durch Interpreter werden dagegen die Maschinenbefehle beim Programmstart oder während der Laufzeit erzeugt.

Manchmal werden Ausdrücke wie „Maschinencode, Maschinensprache, Binärcode, nativer Code, Programmcode“ synonym verwendet.Maschinencode. In: Gabler Wirtschaftslexikon Sie können jedoch zwei unterschiedliche Bedeutungen haben:

Typisierende Bezeichnung des verwendeten Codes als ‚Syntaxbestimmung‘. Beispiel: Interner Binärcode, in dem die Daten in einer Zentraleinheit dargestellt werden. Die für ein ‚bestimmtes Programm‘ vorliegenden Anweisungen. Beispiel „Binärcode (für Programm ABC)“, der vom Computer direkt ausgeführt werden kann.

Maschinenprogramm mini|hochkant=2|,Maschinenprogramm‘, Begriffszusammenhänge und im Sprachgebrauch auftretende Synonyme Maschinenprogramme finden in allen Geräten mit einem Prozessor Verwendung, also von Großrechnern über Personal Computer und Smartphones bis hin zu eingebetteten (embedded) Systemen in modernen Waschmaschinen, Radios oder Steuerungen im Kraftfahrzeug für ABS oder Airbag. Bei PCs sind sie üblicherweise in ausführbaren Dateien enthalten.

Ausführbare Dateien findet man bei Windows in Dateien unter der Dateinamenserweiterung „.exe“. Unter vielen anderen Betriebssystemen werden ausführbare Dateien auch ohne Dateiendung und in anderen Formaten geführt. Sie werden teils anders bezeichnet, z. B. unter z/OS als Lademodul. Bei vielen eingebetteten Systemen oder Mikrocontrollern befinden sich bestimmte Maschinenprogramme permanent im ROM, z. B. ein Bootloader.

Maschinenprogramme können von Menschen mithilfe eines Hex-Editors oder eines Maschinencode-Monitors betrachtet, prinzipiell auch erstellt und verändert werden. In der Praxis erfolgt die Herstellung eines Maschinenprogrammes jedoch mithilfe eines Assemblers oder Compilers unter Verwendung von Quelltext der jeweiligen Programmiersprache. Maschinencode kann durch einen Disassembler wieder in Assemblerformat rückübersetzt werden, die Umwandlung in eine höhere Programmiersprache durch einen Decompiler unterliegt jedoch starken Einschränkungen.

Unterschiede zur Assemblersprache Das Programm im Maschinencode besteht aus einer Folge von Bytes, die sowohl Befehle als auch Daten repräsentieren. Da dieser Code für den Menschen schwer lesbar ist, werden in der Assemblersprache die Befehle durch besser verständliche Abkürzungen, sogenannte Mnemonics, dargestellt. Dabei können der Operationscode, Quell- und Zielfelder sowie andere Angaben in den Befehlen mit symbolischen Bezeichnern (wie MOVE, PLZ, LAENGE) notiert werden, ggf. ergänzt um numerische Zahlenwerte, z. B. für eine individuelle Längenangabe, Registernummern usw.

Dateiformat Ein Assemblerprogramm liegt, wie bei Quelltexten üblich, meist als Textdatei vor, während das Maschinenprogramm in der Regel als Binärdatei gespeichert ist. Anweisungen Das Programmieren im Textformat mit anschließender Übersetzung in den Maschinencode durch einen Assembler gestattet dem Programmierer eine weit schnellere und einfachere Programmerstellung als das Codieren im Maschinencode. In der Regel entspricht einem Assemblerbefehl genau ein Befehl im Maschinencode außer bei Makroassemblern, die aus einer Anweisung mehrere Maschinenbefehle generieren können. Zeichenformate Gängige Assembler erlauben es dem Programmierer, Zeichen und Zahlen in unterschiedlichen Codeformaten (Text, dezimal, Hexadezimal, oktal, binär) zu codieren, und stellen diese im Maschinenbefehl in einem der Anweisung entsprechenden Format ein. Beispiel: Die Quelltextangaben ‚A‘ oder ‚X'C1'‘ oder ‚B'11000001'‘ (im EBCDIC-Code) bedeuten dasselbe und werden im Maschinencode zu X'C1' – was bei Befehlen für duale Operationen dem Wert +193, bei Zeichenoperationen dem Zeichen 'A' entspricht. Datendeklaration Ein Assembler bietet dem Programmierer die Möglichkeit, Datenfelder als solche zu kennzeichnen und zu benennen, sie in verschiedenen Formaten zu deklarieren und sie mit symbolischen Namen zu versehen. Im erzeugten Maschinencode wird gemäß diesen Angaben Speicherplatz reserviert und (bei Konstanten) mit Inhalt vorbelegt. In den erzeugten Maschinenbefehlen wird die symbolische Adresse durch die numerische Adresse ersetzt und die Länge der definierten Felder eingesetzt. Adressierung Ein Assembler ermöglicht es, die Speicherorte für Daten und Befehle symbolisch zu benennen, sodass dem Programmierer deren numerische Adresse nicht bekannt sein muss. In der Maschinensprache sind Speicheradressen direkt angegeben. Selbst bei einer kleinen Änderung des Programms würden sich die Adressen aller nachfolgenden Programmteile verschieben, was (bei Programmierung in Maschinensprache) eine Anpassung all dieser Adressen erforderlich machen würde. Durch die symbolische Adressierung sind in der Assemblersprache auch Unterprogramme aufrufbar, deren tatsächliche Adresse im Maschinencode erst vom Assembler oder einem Linker eingesetzt wird. Programmumfang Ein Assemblerprogramm bezieht sich normalerweise auf eine (1) definierte Aufgabenstellung und ist zur Assemblierungszeit von anderen Programmen unabhängig. Durch Techniken wie das ‚Linken‘ können je nach Entwicklungsplattform die Ergebnisse mehrerer Assemblierungen (z. B. Objektmodule genannt)‚ zusammengefasst werden, die als Gesamtheit das Maschinenprogramm ergeben. Dokumentation Ein Assembler ermöglicht es, einem Programm Kommentare und weitergehende Dokumentation hinzuzufügen. In das Maschinenprogramm werden diese Quellcodeteile in der Regel nicht übernommen.

Die meisten der vorgenannten, zur Assemblersprache genannten Aspekte gelten in ähnlicher Weise auch für höhere Programmiersprachen – wobei diese sich gegenüber der Assemblersprache durch weitere (Leistungs-)Merkmale unterscheiden.

Programmerstellung Intern ist jeder Befehl der Maschinensprache durch einen oder mehrere Zahlenwerte kodiert. Diese Zahlenwerte bestehen aus dem Opcode, der die Art des Befehls festlegt, eventuell gefolgt von einem oder mehreren Bytes an Daten zu diesem Befehl. Eine sinnvolle Folge von solchen Zahlencodes im Hauptspeicher, bzw. als Datei gespeichert, bildet demnach ein Programm. Es gibt nun verschiedene Arten, solche Programme zu erstellen: Direkte Eingabe des Binärcodes (äußerst umständlich und höchst fehleranfällig, seit den 1950er Jahren unüblich). Über einen Hex-Editor den Zahlen-Code in Opcodes zu schreiben (fehleranfällig). Mit einem Assembler: Assemblersprachen formulieren die Prozessorbefehle des Maschinencodes als Mnemonics in einer einfachen Syntax. Dieser Quelltext wird danach vom Assembler in den Maschinencode konvertiert. Ein Programm wird in einer Hochsprache geschrieben, danach von einem Compiler in Maschinencode übersetzt (kompiliert). In einem Zwischenschritt wird dabei häufig zuerst Objektcode erzeugt. Alternativ können Programme in einer Hochsprache auch – entweder nach Kompilierung in einen Zwischencode oder direkt – durch einen Interpreter abgearbeitet werden. Ein Beispiel hierfür ist die Programmiersprache Java, deren Zwischencode (auch Bytecode genannt) von einem Interpreter ausgeführt wird. Dies geschieht für den Benutzer transparent, wenn zum Beispiel ein Applet im Webbrowser ausgeführt wird. Neben Java werden auch sämtliche .NET-Sprachen, wie beispielsweise C#, in einen Zwischencode (englisch Intermediate Language) übersetzt, welcher anschließend zur Laufzeit innerhalb der CLR von einem JIT-Compiler in die entsprechende Maschinensprache übersetzt wird. Bei der Installation von Software, einschließlich des Betriebssystems, liegt diese oft bereits in Maschinencode für die jeweilige Plattform vor. Dies erspart dem Nutzer die Kompilierung des Programms.

Beispiel Programmiersprache C Im folgenden Quelltext in der höheren Programmiersprache C wird die Summe der Zahlen 2 und 3 berechnet und das Ergebnis zurückgegeben:

int main() { int a = 2; int b = 3; int c = a + b; return c; }

Ein solches Programm, würde es für einen x86-Prozessor kompiliert, könnte folgenden Maschinencode ergeben:

Maschinencode(hexadezimal) zugehöriger Assemblercode zugehöriger C-Code Erläuterung 5548 89 E548 83 EC 12 push rbp mov rbp, rsp sub rsp, 12 int main() { Sichere Register RBP auf dem Stack und setze RBP auf den Wert von Register RSP, dem Stackpointer (gehört nicht zur eigentlichen Berechnung). Diese Vorbereitung ist notwendig, um die Werte der Variablen a, b und c auf dem Stack speichern zu können. C7 45 FC 02 mov DWORD PTR [rbp-4], 2 int a = 2; Setze Variable a, die durch Register RBP adressiert wird, auf den Wert 2. C7 45 F8 03 mov DWORD PTR [rbp-8], 3 int b = 3; Setze Variable b, die durch Register RBP adressiert wird, auf den Wert 3. 8B 45 F88B 55 FC01 D089 45 F4 mov eax, DWORD PTR [rbp-8] mov edx, DWORD PTR [rbp-4] add eax, edx mov DWORD PTR [rbp-12], eax int c = a + b; Setze Register EAX auf den Wert von Variable b. Setze Register EDX auf den Wert von Variable a. Addiere den Wert von EDX zum Wert von EAX. Setze Variable c, die durch RBP adressiert wird, auf den Wert von EAX. 8B 45 F4 mov eax, DWORD PTR [rbp-12] return c; Setze Register EAX auf den Wert von Variable c. Weil Register EAX diesen Wert bereits enthält, könnte diese Anweisung in einem optimierten Programm entfallen. 48 83 E55DC3 mov rsp, rbp pop rbp ret } Setze RBP wieder auf seinen ursprünglichen Wert. Springe zurück an die Stelle des Aufrufs von main. Register EAX enthält den Rückgabewert.

Ein Compiler könnte daraus zusammen mit weiteren notwendigen Informationen eine ausführbare Datei erzeugen. Zur Ausführung wird der Maschinencode vom Lader des Betriebssystems in den Arbeitsspeicher geladen. Anschließend ruft die Laufzeitumgebung die Funktion main() auf und die CPU beginnt mit der Abarbeitung der Maschinenbefehle.

Maschinencode bei IBM-Rechnern am Beispiel von OS/390 Der Maschinencode entsteht beim Assemblieren bzw. beim Kompilieren der Quellcodedateien und wird vom „Linkage Editor“, ggf. unter Hinzufügen weiterer Module, als ausführbares Programm in einer Programmbibliothek bereitgestellt. Zur Ausführung wird dieses Programm in den Hauptspeicher geladen. Der Maschinencode dieser Programme enthält Befehle und Daten gemischt – wie dies bei Computern der Von-Neumann-Architektur möglich ist (im Gegensatz z. B. zur Harvard-Architektur).

Die Daten werden entsprechend dem festgelegten Speicherformat angelegt. Der Wert „12“ kann dabei z. B. folgendes Aussehen haben (Darstellung hexadezimal, in minimaler Länge): F1F2 Text oder ungepackte Zahl 012C gepackt positiv, Speicherung je Zahl ein Halbbyte, am Ende ein Vorzeichen-Halbbyte. 012D gepackt negativ (dto) 0C binär positiv, entspricht B'00001100'