Assemblersprache ist eine Low-Level-Programmiersprache, die die Befehle offenlegt, die vom Computer zur Steuerung seiner Hardware verwendet werden. In diesem Artikel beschäftigen wir uns mit Assemblersprache als Einführung in die Programmierung mit Code-Beispielen und Erläuterungen. Wenn Sie sich jemals gefragt haben, was ein „Zeiger” oder „Stack” ist und ob Sie Assembler lernen sollten, um Programmierer zu werden, lesen Sie weiter. In diesem Artikel werden die Assemblersprache, ihre Vor- und Nachteile, Beispiele für häufige Anwendungsfälle von Assemblersprachen und einige Ressourcen für diejenigen, die mehr über dieses Thema erfahren möchten, erläutert. Los geht's!
Definition der Assemblersprache
Assemblersprache ist eine Low-Level-Programmiersprache, die für einen bestimmten Prozessortyp spezifisch ist. Sie wird in der Regel in einer mnemonischen Form geschrieben, die eine symbolische Darstellung des vom Assembler generierten Maschinencodes darstellt. In der Assemblersprache werden die Opcodes der Maschinenbefehle durch Mnemonik ersetzt, und die Adressen der Befehle oder Operanden werden durch Adresssymbole oder Labels ersetzt. In verschiedenen Geräten entspricht die Assemblersprache unterschiedlichen Maschinenbefehlssätzen und wird durch den Assemblierungsprozess in Maschinenbefehle umgewandelt. Es besteht eine Eins-zu-Eins-Entsprechung zwischen einer bestimmten Assemblersprache und einem bestimmten Maschinenbefehlssatz, und sie ist nicht direkt zwischen verschiedenen Plattformen übertragbar.
Geschichte der Assemblersprache
Die Geschichte der Assemblersprache reicht bis in die Anfänge der Informatik zurück. Eine der ersten Assemblersprachen wurde in den 1950er Jahren für den Computer IBM 701 entwickelt. Diese Sprache namens Autocode wurde von Alick Glennie entwickelt und basierte auf dem bestehenden Code, der für den Vorgänger des 701, den IBM 650, verwendet wurde.
Auf Autocode folgten bald eine Reihe weiterer Assemblersprachen, darunter FORTRAN Assembly Language (FAL) und COBOL Assembly Language (CAL). Diese Sprachen wurden entwickelt, um die Programmierung in den jeweiligen Hochsprachen zu vereinfachen, und waren sehr erfolgreich.
Programmiersprache
Seit der Einführung des weltweit ersten elektronischen Computers im Jahr 1946 sind die Art und Weise sowie die Sprache der Kommunikation zwischen Mensch und Maschine zum Hauptforschungsgebiet von Softwareentwicklern und Computerfachleuten geworden. Effizientere und einfachere Programmiersprachen sind zum neuen Liebling der Softwareentwickler geworden. Mit der rasanten Entwicklung der Computer wird die Geschwindigkeit der Hardware-Upgrades immer höher und die Anforderungen an Programmiersprachen immer strenger. Programmiersprachen haben in den letzten Jahrzehnten einen langen Weg zurückgelegt, und bis heute gab es drei Generationen von Sprachen. Um den Programmieranforderungen und Softwarefunktionen in verschiedenen Bereichen gerecht zu werden, wurden zahlreiche Programmiersprachen modifiziert, ersetzt und weiterentwickelt, was schließlich zur Diversifizierung der aktuellen Programmiersprachen führte. Trotz vieler Versuche, eine universelle Sprache zu finden, die sich an alle Programmierumgebungen anpassen kann, war keiner davon erfolgreich. Die Programmiersprache schreitet mit der modernen Technologie voran, und die Weisheit des Menschen kommt immer mehr zum Ausdruck.

1. Generation: Maschinensprache
Maschinensprache ist die Programmiersprache der ersten Generation. Zu Beginn der Erfindung des Computers konnten Menschen, um den Computer zur Ausführung ihrer eigenen Aufgaben oder Projekte zu steuern, nur binäre Zahlenfolgen wie „0“ und „1“ schreiben, um den Computer zu steuern. Diese Sprache ist die Maschinensprache. Intuitiv ist die Maschinensprache sehr undurchsichtig und schwer zu verstehen, und ihre Bedeutung wird oft durch Nachschlagen in Tabellen oder Handbüchern verstanden. Die Verwendung ist sehr mühsam, insbesondere wenn Sie das fertige Programm ändern müssen. Diese Art von ungeordneter Maschinensprache macht es Ihnen unmöglich, zu starten, und es ist schwierig, Programmfehler zu finden. Darüber hinaus ist die Betriebsumgebung verschiedener Computer unterschiedlich, und auch die Anweisungen und Bedienungsmethoden sind unterschiedlich. Wenn Sie also eine Besonderheit in dieser Maschinensprache haben, können Sie sie nur auf einem bestimmten Computer ausführen. Und sobald Sie den Computer wechseln, müssen Sie neu programmieren, was die Nutzungs- und Förderungs-Effizienz des Programms stark reduziert. Aufgrund der Besonderheit der Maschinensprache ist sie jedoch perfekt an einen bestimmten Computertyp angepasst, sodass ihre Betriebseffizienz viel höher ist als bei anderen Sprachen.

2. Generation: Assemblersprache
Es ist nicht schwer zu erkennen, dass Maschinensprache als Programmiersprache eine geringe Flexibilität und Lesbarkeit aufweist. Um die Unannehmlichkeiten zu verringern, die Maschinensprache für Softwareentwickler mit sich bringt, wurde sie weiterentwickelt und verbessert: Anstelle einer bestimmten Anweisung werden leicht verständliche und einprägsame Buchstaben und Wörter verwendet. Durch diese Methode ist es für Menschen einfacher, das fertige Programm zu lesen oder die Funktion des Programms zu verstehen, und die Fehlerbehebung sowie der Betrieb und die Wartung des bestehenden Programms werden einfacher und bequemer. Diese Sprache bezeichnen wir als Assemblersprache, die Computersprache der zweiten Generation.

Im Vergleich zur Maschinensprache weist die Assemblersprache eine höhere Maschinenabhängigkeit auf und ist leichter zu merken und zu schreiben, behält aber gleichzeitig die hohe Geschwindigkeit und Effizienz der Maschinensprache bei. Die Assemblersprache ist nach wie vor eine maschinenorientierte Sprache, es ist schwierig, die Absicht des Programmdesigns anhand ihres Codes zu verstehen, und das entworfene Programm lässt sich nicht leicht übertragen, sodass sie nicht so weit verbreitet ist wie die meisten anderen höheren Computersprachen. Daher wird sie in den heutigen hochentwickelten Hochsprachen in der Regel auf der untersten Ebene verwendet, meist zur Programmoptimierung oder für den Hardwarebetrieb.
3. Generation: Hochsprache
Nachdem die Programmiersprache die Aktualisierung der Maschinensprache, Assemblersprache usw. durchlaufen hatte, entdeckten die Menschen den entscheidenden Faktor, der die Verallgemeinerung von Programmen einschränkt – die Programmportabilität. Es muss ein Programm entwickelt werden, das unabhängig von der Computerhardware auf verschiedenen Maschinen ausgeführt werden kann. Auf diese Weise können viele sich wiederholende Programmierprozesse vermieden und die Effizienz verbessert werden. Gleichzeitig sollte die Sprache der mathematischen Sprache oder der natürlichen Sprache des Menschen nahekommen. In den 1950er Jahren, als Computer noch rar waren, entstanden die ersten höheren Programmiersprachen. Zu dieser Zeit waren die Kosten für Computer hoch, aber die Rechenleistung pro Tag war begrenzt. Die Frage, wie man die begrenzte Rechenleistung von Computern effektiv nutzen kann, wurde zu einem Problem, mit dem sich die Menschen damals konfrontiert sahen. Gleichzeitig wurde aufgrund der Knappheit der Ressourcen auch die Betriebseffizienz von Computern zu einem Ziel, das von den Ingenieuren dieser Zeit verfolgt wurde.

Assemblersprache-Komposition
Aufgrund des umfangreichen Assembler-Befehlssystems ist es notwendig, ein Befehlssystem aufzubauen, das eine große Anzahl von Befehlen, komplexe Formate und eine schlechte Merkbarkeit aufweist. Der schwierigste Teil des Befehls ist der vom Befehl unterstützte Adressierungsmodus, dessen Kern darin besteht, wie der Operand im Befehl abgerufen wird. Für den Prozessor geht es darum, wie er die benötigten Daten findet. Für die Assemblersprache auf der untersten Ebene des Computers ist diese Adressierungsmethode jedoch mit einer Vielzahl von Speicherformaten verbunden und steht in engem Zusammenhang mit der komplexen Speicherverwaltung, sodass sie schwer zu verstehen ist. Schließlich hängen Assemblerbefehle auch damit zusammen, wie sie Flags beeinflussen, aber Prozessorflags sind sehr komplex, sodass es schwieriger ist, den Mechanismus zu verstehen.
Befehl senden
Die Befehle zum Senden umfassen:
- allgemeine Datenübertragungsanweisung: MOV;
- Bedingte Übertragungsanweisung: CMOVcc;
- Befehl für Stapeloperationen: PUSH, PUSHA, PUSHAD, POP, POPA, POPAD;
- Austauschbefehl: XCHG, XLAT, BSWAP;
- Befehl zur Übertragung von Adress- oder Segmentdeskriptor-Selektoren: LEA, LDS, LES, LFS, LGS, LSS usw.
logische Operation
Dieser Teil der Anweisungen dient zur Durchführung arithmetischer und logischer Operationen, darunter:
- Additionsbefehl: ADD, ADC;
- Subtraktionsanweisung: SUB, SBB;
- Plus-Eins-Befehl: INC;
- Dezimalanpassungsbefehle: AAA, AAS, DAA, DAS;
- Minus-Eins-Befehl: DEC;
- Vergleichsoperation: CMP;
- Vorzeichen-Erweiterungsbefehle: CBW, CWDE, CDQE;
- Multiplikationsbefehl: MUL, IMUL;
- Divisionsbefehl: DIV, IDIV;
- logische Operationsbefehle: AND, NOT, OR, XOR, TEST.
Verschiebungsanweisung
Dieser Teil der Anweisung wird verwendet, um einen Register- oder Speicheroperanden eine bestimmte Anzahl von Malen zu verschieben.
- Befehl für logische Linksverschiebung: SHL;
- Befehl für logische Rechtsverschiebung: SHR;
- Befehl für arithmetische Linksverschiebung: SAL;
- Arithmetische Rechtsverschiebungsanweisung: SAR;
- Befehl für zirkuläre Linksverschiebung: ROL ;
- Befehl für zirkuläre Rechtsverschiebung: ROR usw.
Bitmanipulation
Dieser Teil der Anweisungen umfasst:
- die Bit-Test-Anweisung: BT;
- die Bit-Test- und Set-Anweisung: BTS;
- die Bit-Test- und Rücksetzanweisung: BTR;
- die Bit-Test- und Negationsanweisung: BTC;
- die Befehlsfolge zum Vorwärtsscannen von Bits: BSF;
- die Bit-Rückwärtsscan-Anweisung: BSR.
Kontrollübertragung
Dieser Teil umfasst:
- unbedingte Sprunganweisung: JMP;
- bedingte Sprunganweisung: JCC, JCXZ;
- Schleifenbefehl: LOOP, LOOPE, LOOPNE;
- Prozeduraufrufbefehl: CALL;
- Rückkehrbefehl für Unterprozeduren: RET;
- Interrupt-Befehl: INTn, INT3, INTO, IRET usw.
Zeichenfolgenbearbeitung
Dieser Teil der Anweisungen dient zur Verarbeitung der Datenfolge, einschließlich:
- den Befehl zum Übertragen von Strings: MOVS;
- den Befehl zum Vergleichen von Strings: CMPS;
- den Befehl zum Scannen von Strings: SCANS;
- den Befehl zum Speichern von Zeichenfolgen: STOS;
- die Befehlsfolge zum Laden der Zeichenfolge: LODS.
Eingabe Ausgabe
Dieser Teil der Anweisungen dient zum Austausch von Daten mit Peripheriegeräten, einschließlich der Port-Eingabeanweisungen IN/INS und der Port-Ausgabeanweisungen OUT/OUTS.
Beispiel für Assemblersprache
Hier ist ein einfaches Assemblerprogramm, das zwei Zahlen addiert:
; add.asm
;
; This program adds two numbers together
;
section .data
; These are the two numbers we will be adding
; We must store them in memory so the CPU can access them
num1: dw 1234
num2: dw 5678
section .text
; This is the code section of the program
; The code is a set of instructions for the CPU to execute
global _start
_start:
; Load the two numbers into registers
mov eax, [num1]
mov ebx, [num2]
; Add the numbers together
add eax, ebx
; Store the result in the num1 memory location
mov [num1], eax
; Exit the program
mov eax, 1
int 0x80
Merkmale der Assemblersprache
1. Maschinenabhängigkeit
Dies ist eine maschinenorientierte Sprache auf niedriger Ebene, die in der Regel für einen bestimmten Computer oder eine bestimmte Computerfamilie entwickelt wurde. Da es sich um eine symbolische Darstellung von Maschinenbefehlen handelt, haben verschiedene Maschinen unterschiedliche Assemblersprachen.
2. Hohe Geschwindigkeit und Effizienz
Die Assemblersprache behält die Vorteile der Maschinensprache bei und zeichnet sich durch Direktheit und Einfachheit aus. Sie kann effektiv auf verschiedene Hardwaregeräte des Computers zugreifen und diese steuern, wie z. B. Festplatten, Speicher, CPU, E/A-Ports usw., benötigt weniger Speicherplatz und hat eine schnelle Ausführungsgeschwindigkeit. Sie ist eine effiziente Programmiersprache.
3. Komplexität beim Schreiben und Debuggen
Da die Hardware direkt gesteuert wird und auch einfache Aufgaben viele Assemblersprachenanweisungen erfordern, müssen bei der Programmierung alle Aspekte berücksichtigt werden. Alle möglichen Probleme müssen berücksichtigt werden, und verschiedene Software- und Hardware-Ressourcen sollten sinnvoll zugewiesen und genutzt werden. Auf diese Weise erhöht sich zwangsläufig die Belastung für den Programmierer. Ebenso ist es beim Debuggen eines Programms schwierig, Probleme im Programmablauf zu finden, sobald diese auftreten.
Vorteile
Als Programmiersprache der zweiten Generation oberhalb der Maschinensprache hat die Assemblersprache ebenfalls viele Vorteile:
- Sie kann den Speicherstatus und den Status der Hardware-E/A-Schnittstelle leicht lesen.
- Der geschriebene Code kann präzise ausgeführt werden, da es viel weniger Kompilierungsverknüpfungen gibt.
- Als Low-Level-Sprache ist sie in hohem Maße erweiterbar.
Nachteile
- Da der Code sehr monoton ist und nur wenige Sonderzeichen enthält, ist er sehr ausführlich und schwer zu schreiben.
- Da die Assembler-Sprache immer noch selbst den Speicher aufrufen muss, um die Daten zu speichern, kommt es leicht zu Fehlern, die nicht einfach zu beheben sind.
- Selbst wenn ein Programm fertiggestellt ist, nimmt seine spätere Wartung viel Zeit in Anspruch.
- Aufgrund der Besonderheiten der Maschine kommt es zu einer schlechten Code-Kompatibilität.
Assemblersprache vs. Maschinensprache
Der Hauptunterschied zwischen Assemblersprache und Maschinensprache besteht darin, dass Assemblersprache eine Low-Level-Programmiersprache ist, die einen separaten Assembler benötigt, um sie in Maschinencode zu übersetzen, während Maschinensprache eine direkte Darstellung des zugrunde liegenden Maschinencodes ist.
Assemblersprache ist für Menschen besser lesbar als Maschinensprache, aber dennoch relativ schwer zu lesen und zu schreiben. Sie ist so konzipiert, dass sie dem nativen Maschinencode nahekommt, sodass Programmierer leicht verstehen können, was der Code tut. Dies erschwert jedoch auch das Schreiben von portierbarem Code, da der Code eng mit der spezifischen Architektur der Maschine verbunden ist.
Maschinensprache hingegen ist der native Code für die Maschine und für Menschen nicht lesbar. Sie wird direkt vom Prozessor ausgeführt und ist daher effizienter als Assemblersprache. Allerdings ist sie viel schwieriger zu programmieren, da der Programmierer sich mit den zugrunde liegenden Maschinencode-Befehlen auseinandersetzen muss.
Ressourcen zum Erlernen der Assemblersprache
Wenn Sie mehr über Assemblersprache erfahren möchten, stehen Ihnen viele verschiedene Ressourcen zur Verfügung. Bücher über Assemblersprache finden Sie bei Amazon und in lokalen Buchhandlungen. Außerdem gibt es Online-Kurse auf Websites wie Coursera, edX und Udemy. Wenn Sie mehr über Computerarchitektur erfahren möchten, gibt es ebenfalls viele Bücher zu diesem Thema. Diese Ressourcen können Ihnen helfen, zu verstehen, was Assemblersprache ist und welche Auswirkungen sie auf das Design von Computerhardware und -software hat.




