Du bist nicht angemeldet.

Lieber Besucher, herzlich willkommen bei: DeveloperTalk. Falls dies dein erster Besuch auf dieser Seite ist, lies bitte die Hilfe durch. Dort wird dir die Bedienung dieser Seite näher erläutert. Darüber hinaus solltest du dich registrieren, um alle Funktionen dieser Seite nutzen zu können. Benutze das Registrierungsformular, um dich zu registrieren oder informiere dich ausführlich über den Registrierungsvorgang. Falls du dich bereits zu einem früheren Zeitpunkt registriert hast, kannst du dich hier anmelden.

meschi

Fortgeschrittener

  • »meschi« ist der Autor dieses Themas

Beiträge: 263

Registrierungsdatum: 23.08.2011

Wohnort: /

Danksagungen: 40

  • Private Nachricht senden

1

22.02.2012, 20:39

AT&T Syntax Assembler Tutorial -- LINUX

//UNDER CONSTRUCTION

Hallo,
ich hatte eben mal die Idee, ein Assembler Tutorial für AT&T Syntax Assembler zu schreiben. Ein Tutorial für Intel-Syntax findet ihr von Simon D.. Ich persönlich finde die Syntax schöner und einfacher verständlich als die Intel Syntax, wobei sehr viele andere der komplett gegenteiligen Meinung sind. Ich schreibe dieses Tutorial, da ich wenig AT&T Assembler Tutorials bisher gefunden habe und erst recht keine auf deutsch. Ich werde mich hier auf GAS unter i386* Linux beschränken.
Der Fokus dieses Tutorials wird auf der Anwendungsentwicklung liegen, dh auf der direkten Einbindung bzw. Programmierung auf Linux als Anwendungsprogramm. Natürlich werdet ihr viele teile hier auch für andere Zwecke verwenden können, allerdings werde ich mich hier auf Entwicklung von Binarys für linux konzentrieren.

TEIL 1: Der Prozessor

Dieser Teil erklärt die Grundlegenden Funktionsprinzipien des Prozessors. Dieser Text wird auf das nötigste, das zum Assemblerprogrammieren und fürs Verständnis notwendig ist eingehen.
Ein Prozessor versteht keine Programmiersprache, wie zum Beispiel C. Der Prozessor, in Zukunft aus Platzgründen CPU genannt, arbeitet mit einer eigenen "Sprache", der Assemblersprache. Ein Befehl dieser Sprache wird als Opcode bezeichnet. Der Opcode ist wie alle Daten auf Hardwareebene eine Zahl. Dieser Opcode wird durch ein Mnemonic repräsentiert. Mnemonics werden verwendet, damit man beim Assembler Programmieren keine Zahlen schreiben muss, sondern besser lesbare Zeichenfolgen verwenden kann. Der Prozessor hat zum Arbeiten direkt Register zur Verfügung. Die Register zum direkten "arbeiten" sind folgende:
  • EAX
  • EBX
  • ECX
  • EDX

Diese Register sind 32bit groß.
BSP: EAX
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
EAX (32bit)
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
UNBENANNT (16bit) | AX (16bit)
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| | AH (8bit) | AL (8bit)
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//FIXME: Richtige Tabelle

EAX setzt sich aus AX und nicht direkt adressierbaren 16bit zusammen. AX besteht aus AH und AL. Alle benannten Register(unter)namen sind direkt ansprechbar.

Desweiteren wäre da noch das Register mit dem Instruction Pointer wichtig. Das Register ist ebenfalls 32bit groß und enthält eine Zahl, die die Speicheraddresse Angibt, an der die aktuell ausgeführte Instruktion (Befehl) steht. Der Prozessor lädt immer die Instruktion, auf die durch die angegebene Speicheradresse gezeigt wird, und führt sie aus (Sehr stark vereinfacht ;)).
Der Prozessor kann in einer Instruktion nur einen Speicherzugriff machen (aber dazu später mehr). Auch kennt der Prozessor keine Schleifen, if...else oder switch Konstrukte, die ihr aus Hochsprachen vielleicht kennt. Es gibt nur Sprunganweisungen, sogenannte Jumps. Diese wären vom Grundprinzip vergleichbar mit einem GOTO in Hochsprachen. Als Operand für die Jump-Anweisung wird eine Speicheradresse gefordert.
Wenn gejumpt wird, wird der Instruction Pointer auf die angegebene Speicheraddresse gesetzt.
Der Speicher wird in 8bit schritten (1byte) durchnummeriert.
Als grundlegende Instruktionen können aber Arithmetische, Speicherzugriffs-, Sprung- und Vergleichsinstruktionen genannt werden.



TEIL 2: x86 32bit Assembler unter Linux, GnuASsembler, AT&T Syntax:
So hier einmal ein bischen Code um mit dem Umgang mit dem Assembler vertraut zu werden:
Wichtig: Ihr müsst das % immer direkt vor den Registernamen schreiben

Quellcode

1
2
3
4
5
6
.section .text
.global main
main:
mov % eax, % ebx 
#das leerzeichen zwischen % und Registername 
#muss raus, aber sonst bekomme ich so komische buchstaben: ê

Das speichern wir jetzt als foo.S
Das tolle an GCC ist, dass es die GnuCompilerCollection ist. Das heißt, wir können jetzt einfach unseren Assemblercode direkt mit GCC assemblieren. Dazu gebt ihr in der konsole:
$ gcc foo.S -o foo
ein. Mit ./foo könnt ihr das programm starten. Im Moment tut das Programm noch nichts.


Schauen wir uns den Code an:

Quellcode

1
.section .text

Das bedeutet, dass hier der Bereich anfängt, in dem die Assemblerbefehle stehen, das heißt der ausführbare Teil. Der name .text ist ein bischen irreführend, aber man gewöhnt sich dran.

Quellcode

1
.global .main

Diese Zeile sagt, das das Label "main" auch von außen sichtbar ist. Das wird benötigt, da der Linker nach initialisieren des Programms hier hin springt. Doch später mehr zu Labels.

Quellcode

1
mov % eax, % ebx

Hier haben wir den ersten richtigen Assembler-Befehl. "mov" ist das Mnemonic für einen Speicherzugriff. Dabei wird der Wert von Operand a in operand b kopiert. Hier wird der inhalt von eax in ebx kopiert.

Das war jetzt das erste fertige Assemblerprogramm. Ziemlich nutzlos, aber hey! :D

MOV
An dieser Stelle lohnt es sich die essenzielle Instruktion "mov" zu betrachten.
Die allgemeine Syntax für "mov" ist:
mov Quelle, Ziel

Quelle und Ziel können sowohl Register, numerische Werte oder Speicheraddressen sein. Dies gilt übrigends auch für alle asm (Assembler) Befehle.

Register:
Register werden in der AT&T Assembler Syntax immer beginnend mit einem Prozentzeichen angegeben: % eax, % ebx, %eip, %ah, ...
Numerische Werte:
Numerische Werte werden immer mit einem vorangestellten Dollar-Zeichen gekenzeichnet: $1, $0xFC, $24532, ...
Speicheraddressen:
Speicheraddressen sind einfache Zahlen ohne Präfix: 0, 0x33, 0xF13, 1337, ...

Details im Bezug auf Register:
mit %Register greift man auf den darin enthaltenen Wert als numerischen Wert zu. Will man das, was was an der Addresse steht, die in
dem Register steht, haben muss man das register mitsamt dem '%' zeichen in Klammern setzen (%Register)

Beispiele:

Quellcode

1
2
3
4
5
mov % eax, % ebx #kopiert inhalt von eax in ebx
mov $1, % eax #schreibt die Zahl 1 in das Register eax
mov 0xB00B5, % ecx #kopiert 4 Byte aus dem Speicher an der stelle 0xB00B5 in ecx
mov $0xCAFE, 0x1005E2
mov % eax, $42 #Fehler


Das Ziel muss immer ein Register oder eine Speicheraddresse sein, da es keinen Sinn machen würde den inhalt von eax in die Zahl 42 zu schreiben.

Wenn ihr die Beispiele ausprobiert habt, werdet ihr gemerkt haben, dass es bei

Quellcode

1
mov $0xCAFE, 0x1005E2

eine Fehlermeldung kommt. Bei mir sieht sie so aus, sie kann aber variieren:

Quellcode

1
Error: no instruction mnemonic suffix given and no register operands; can't size instruction


Hier kommt eine weitere Eigenschaft der AT&T Syntax zutage, die bei der Intel-Syntax gänzlich fehlt: Das Instruction Mnemonic Suffix
Das bedeutet einfach, dass dem Mnemonic wie hier dem "mov" ein buchstabe angehängt wird:
  • b für Byte (8bit)
  • w für Word (16bit) //entspricht short in C
  • l für Long Word (32bit) //entspricht int / long int in C**
  • q für Quad Word (64bit) //entspricht long long int in C
Damit weiß der Assembler beim Assemblieren, wie viel Bits der Kopierte Wert im Speicher später verbrauchen wird.

ADD
Die "add" Instruktion:
Die Syntax ist:
add Quelle, Ziel
Dabei gilt für die Operanden dasselbe wie bei "mov ", das Ergebniss der Addition wird in dem zweiten Operanden gespeichert (<>Intel Syntax: in dem ersten)

Hiier kommt jetzt ein kleiner vergleich von intel und at&t syntax:

Quellcode

1
2
3
4
5
6
7
;intel syntax
[SECTION .text]
global _start
_start:
    xor eax, eax
    mov eax, 0x44
    jmp _start

Quellcode

1
2
3
4
5
6
7
//at&t syntax
.section .text
.global _start
_start:
    xor %eax, %eax
    mov $0x44, %eax
    jmp _start

To be continued... :D

LG,
meschi

*Der absolut hässlichsten verkacktesten verkrüppeltsten scheiß Architektur der Welt
**Hier ist anzumerken, dass auf einem 16bit system ein int in C 16 bit lang ist, ein long int jedoch 32. Auf einem 32bit System sind beide gleich lang. Da ich mich aber auf die i386 Architektur beziehe ist das oben soweit korrekt

Dieser Beitrag wurde bereits 14 mal editiert, zuletzt von »meschi« (19.03.2012, 20:13) aus folgendem Grund: Vergleich mit der Intel syntax


Es haben sich bereits 5 registrierte Benutzer bedankt.

Benutzer, die sich für diesen Beitrag bedankt haben:

Patrick (22.02.2012), Simon (23.02.2012), cedi (26.02.2012), Drakor (03.03.2012), Johannes S. (04.03.2012)

Johannes S.

Fortgeschrittener

Beiträge: 444

Registrierungsdatum: 24.06.2011

Wohnort: Lychen

Danksagungen: 71

  • Private Nachricht senden

2

03.03.2012, 15:47

//FIXME: Richtige Tabelle

Fehlt da noch was? :D
Signatur ?

Drakor

Fortgeschrittener

Beiträge: 204

Registrierungsdatum: 30.06.2011

Danksagungen: 105

  • Private Nachricht senden

3

03.03.2012, 21:39

ansonsten bleibt mir nur übrig zu sagen:

Danke, dass du dir die Mühe für dieses Tutorial gemacht hast !

Vllt. noch kleine Anmerkung: Ich fände es nicht schlecht, wenn du nochmal eine Übersicht der verschiedenen Assembler, die es für Win/Linux gibt, machen könntest und deren Benutzung einmal zeigst oder so.


Gruß
Drakor

Simon D.

Schüler

Beiträge: 109

Registrierungsdatum: 08.07.2011

Danksagungen: 41

  • Private Nachricht senden

4

04.03.2012, 11:21

ich bleibe bei der Intel Syntax. Bzw. ich habe ja blos ein 16bit ASM Tutorial gegeben. Ich glaube ich sollte auch mal ein 32bit Tutorial machen.
Und ich finde das X86 (i386) nicht verkrüppelt ist. Sie ist ganz OK. Klar der Assembler für RISC Prozessoren und für den Power PC sind schöner. Aber X86 ist halt sehr weit verbreitet und wenn man ein eigenes OS schreibt sollte man sich nicht zu sehr an ASM verkrallen wenn man es eh auf andere Plattformen portieren will (via HAL).

LG
Simon

meschi

Fortgeschrittener

  • »meschi« ist der Autor dieses Themas

Beiträge: 263

Registrierungsdatum: 23.08.2011

Wohnort: /

Danksagungen: 40

  • Private Nachricht senden

5

11.03.2012, 20:20

@Simon D.
mein problem sind ja nicht die normalen instruktionen.
Schreib mal ein os mit bootloader das bis in den 64-bit mode lädt :D
ich meine...
den sollte man auch gleich in 64 bit starten können

meschi

Fortgeschrittener

  • »meschi« ist der Autor dieses Themas

Beiträge: 263

Registrierungsdatum: 23.08.2011

Wohnort: /

Danksagungen: 40

  • Private Nachricht senden

6

19.03.2012, 20:08

wollt ihr ein tutorial wo ich so ein bischen was über angewandte assemblerprogrammierung schreibe?

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »meschi« (20.03.2015, 15:33)


Es hat sich bereits 1 registrierter Benutzer bedankt.

Benutzer, die sich für diesen Beitrag bedankt haben:

Alex (24.03.2012)

Simon

Profi

Beiträge: 725

Registrierungsdatum: 14.06.2011

Danksagungen: 210

  • Private Nachricht senden

7

19.03.2012, 20:09

Von mir aus gerne :)

cedi

Profi

Beiträge: 702

Danksagungen: 78

  • Private Nachricht senden

8

20.03.2012, 23:39

Ja! Auf jedenfall!

meschi

Fortgeschrittener

  • »meschi« ist der Autor dieses Themas

Beiträge: 263

Registrierungsdatum: 23.08.2011

Wohnort: /

Danksagungen: 40

  • Private Nachricht senden

9

20.03.2012, 23:46

also wenn ich eins machen würde, dann will ich wenigstens, dass viele leute das lesen wollen.

Es hat sich bereits 1 registrierter Benutzer bedankt.

Benutzer, die sich für diesen Beitrag bedankt haben:

cedi (21.03.2012)

Erik

Profi

Beiträge: 1 274

Registrierungsdatum: 22.06.2011

Wohnort: Deutschland ;)

Danksagungen: 307

  • Private Nachricht senden

10

22.03.2012, 18:09

ja mach mal :D
würd mich interessieren
Beste Webite im Internet ( ͡° ͜ʖ ͡°)
xinra.de

Alex

Fortgeschrittener

Beiträge: 372

Registrierungsdatum: 23.06.2011

Wohnort: /home/alex

Danksagungen: 117

  • Private Nachricht senden

11

24.03.2012, 19:18

Ich würds auch definitiv lesen ;)
alexthinking.com - yet another computer weblog

Zitat

Chuck Norris knows the state of schroedinger's cat.

Es hat sich bereits 1 registrierter Benutzer bedankt.

Benutzer, die sich für diesen Beitrag bedankt haben:

cedi (24.03.2012)

Ähnliche Themen

Verwendete Tags

as, asm, assembler, AT&T, gas, glibc, linux, Tutorial