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.

Von Tom Heinrich
GNU Assembler, GAS, AT&T-Syntax, x86-64

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.

1

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.

2

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.

3

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
4

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.

5

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.

6

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.

7

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.

8

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.