Blog / Entwicklung / Assembler
GAS: Warum AT&T-Syntax gar nicht so schlimm ist
Quelle, Ziel, Registerpräfixe – logisch statt geheimnisvoll.
Wer GNU Assembler zum ersten Mal sieht, stolpert meist über Prozentzeichen, Dollarzeichen und eine scheinbar verkehrte Operandenreihenfolge. Hinter diesen Regeln steckt jedoch ein erstaunlich konsistentes System.
GNU Assembler, meist kurz GAS genannt, ist ein zentraler Bestandteil
der GNU-Toolchain. Er begegnet einem beim direkten Schreiben von Assembler,
beim Lesen von Compiler-Ausgaben und beim Debuggen mit Werkzeugen wie
gdb oder objdump.
Auf x86-Systemen verwendet GAS traditionell die AT&T-Syntax. Sie wirkt zunächst ungewohnt, besonders wenn man zuvor Intel-Syntax gesehen hat. Nach wenigen Regeln wird sie jedoch gut lesbar und vor allem eindeutig.
Quelle zuerst, Ziel danach
Der auffälligste Unterschied zur Intel-Syntax ist die Reihenfolge der Operanden. AT&T schreibt zuerst die Quelle und danach das Ziel.
Die Instruktion movl %eax, %ebx bedeutet daher:
Kopiere den 32-Bit-Wert aus %eax nach %ebx.
Dieselbe Operation in zwei Schreibweisen
# AT&T-Syntax: Quelle, Ziel
movl %eax, %ebx
; Intel-Syntax: Ziel, Quelle
mov ebx, eax
Beide Zeilen beschreiben dieselbe Maschinenoperation. Nur die textuelle Darstellung unterscheidet sich.
Register beginnen mit einem Prozentzeichen
Register werden in AT&T-Syntax mit % markiert:
%rax, %eax, %al oder %rsp.
Das Präfix macht sofort sichtbar, dass es sich nicht um einen symbolischen Namen oder eine Speicheradresse handelt.
Konstanten beginnen mit einem Dollarzeichen
Das Dollarzeichen kennzeichnet einen direkten Wert, also ein Immediate.
$1 bedeutet die Zahl 1.
Ohne Dollarzeichen könnte derselbe Ausdruck je nach Kontext als Speicheroperand interpretiert werden.
Ein Wert wird zu einem Register addiert
# eax = eax + 1
addl $1, %eax
Das Suffix beschreibt die Größe
Viele x86-Instruktionen erhalten in GAS ein Suffix:
b für Byte, w für Word,
l für 32 Bit und q für 64 Bit.
movb, movl und movq zeigen dadurch direkt,
wie viele Daten bewegt werden.
Speicheroperanden verwenden Klammern
Ein Ausdruck wie (%rax) greift auf den Speicher an der Adresse zu,
die in %rax gespeichert ist.
Komplexere Adressierung folgt dem Schema
displacement(base, index, scale).
8(%rax,%rcx,4) bedeutet entsprechend:
8 + rax + rcx × 4.
Sprungmarken bleiben erstaunlich normal
Labels funktionieren so, wie man es erwartet. Ein Name mit Doppelpunkt definiert eine Marke, und Sprunginstruktionen verweisen darauf.
Eine kleine Schleife
.section .text
.global _start
_start:
movl $1, %eax
movl $1, %ecx
.Lloop:
cmpl $10, %ecx
jg .Lend
addl %ecx, %eax
incl %ecx
jmp .Lloop
.Lend:
movl $60, %eax
xorl %edi, %edi
syscall
Das Beispiel kombiniert Labels, direkte Werte, Register und die Quelle-Ziel-Reihenfolge in einem zusammenhängenden Ausschnitt.
Warum Compiler-Ausgaben oft AT&T verwenden
GCC, objdump und GDB verwenden in vielen Linux-Umgebungen
standardmäßig AT&T-Syntax.
Wer diese Notation lesen kann, versteht Compiler-Ausgaben, Disassemblierungen und Abstürze deutlich schneller.
Warum das für t8core wichtig ist
t8core-Anwendungen werden nicht vollständig in Assembler geschrieben. GAS ist dennoch wichtig, wenn Compiler-Code geprüft, Performance analysiert, Systemaufrufe verstanden oder Fehler in optimierten Builds untersucht werden.
Bei OCR, Bildverarbeitung und sensibler Dokumentenverarbeitung zählt nicht nur, dass Code funktioniert. Entscheidend ist auch, welche Speicherzugriffe, Instruktionen und Systemübergänge tatsächlich entstehen.
Wichtiger Punkt
AT&T-Syntax ist keine andere Art von Assembler. Sie ist lediglich eine andere Schreibweise für dieselben Maschineninstruktionen.
Kurzfassung
- Quelle steht vor dem Ziel
- Register beginnen mit
% - Direkte Werte beginnen mit
$ - Suffixe zeigen die Operandengröße
- GAS ist in der GNU- und Linux-Welt allgegenwärtig
Fazit
Die AT&T-Syntax wirkt nur so lange fremd, bis ihre wenigen Grundregeln sitzen. Danach wird sie zu einem nützlichen Werkzeug beim Lesen von Compiler-Ausgaben, beim Debuggen und beim Verständnis der tatsächlichen CPU-Arbeit.
Man muss sie nicht religiös bevorzugen. Es genügt, sie sicher lesen zu können. Die CPU interessiert sich ohnehin für keine Syntaxdebatte. Sie bekommt am Ende Bytes.