x86-64 Assembler-Programmierung

H. Högl, 6. Dezember 2018

Ergänzung im Fach Systemnahe Programmierung (http://hhoegl.informatik.hs-augsburg.de/hhwiki/SysProg)

Inhalt

1   Einführung

img/arch64.png

(entnommen aus Introduction_to_x64_Assembly.pdf)

img/register.png

Die General-Purpose Register mit den Namen der 64-, 32-, 16- und 8-Bit Teile (entnommen aus [BH])

1.1   Funktionen

  • Argumente werden nicht mehr auf dem Stack übergeben, sondern in Registern: rdi, rsi, rdx, rcx, r8, r9. Gleitkommazahlen (float, double) werden in den Registern xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7 übergeben.

    img/args.png

    Alle weiteren Argumente werden auf dem Stack übergeben in der Reihenfolge von rechts nach links.

  • Der Stack-Pointer muss vor dem Aufruf einer Funktion auf eine 16-Byte Grenze gesetzt werden. Direkt nach dem Aufruf der Funktion mit call ist die Return-Adresse (8 Byte) auf dem Stack, so dass der Stack innerhalb der Funktion wieder auf eine 16-Byte Grenze gesetzt werden muss.

  • Die aufgerufene Funktion muss folgende Register erhalten: rbp, rbx, r12, r13, r14, r15 ("callee-save registers").

  • Rückgabewerte von Funktionen sind in rax oder rdx:rax. Bei einem Gleitkommawert ist es xmm0 oder xmm1:xmm0.

Beispiele:

  • simple_l (aus [BH]). Der Quelltext code.c ist einmal für 32-Bit und einmal für 64-Bit generiert worden. Man sieht die unterschiedliche Übergabe der Argumente.
  • simple_i (aus [BH]) Der Datentyp der Argumente wurde von long int auf int geändert. Das spiegelt sich in der Registerbreite wieder.

1.2   Systemaufrufe

Bei 64-Bit Linux haben die Systemaufrufe andere Nummern als bei 32-Bit! Eine Tabelle mit den 64-Bit Systemaufrufen findet man z.B. unter: https://filippo.io/linux-syscall-table/ oder http://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/.

Der Systemaufruf wird mit dem neuen syscall Maschinenbefehl gemacht, nicht wie bei 32-Bit mit int $0x80.

Beispiel

1.3   Aufrufe der libc

Beispiel

1.5   C und Assembler mischen

Beispiel

  • max (aus [RAY])

2   Beispielprogramme im Internet

GNU Assembler

Intel Syntax / Nasm / Yasm

(Programme in der Intel Syntax kann man entweder mit nasm oder yasm übersetzten. Die Kommandozeile für nasm und yasm lauten etwa so:

nasm -f elf64 -l demo.lst demo.s

yasm -m amd64 --list=demo.lst -f elf -gstabs -D ELF_TYPE demo.s

3   Literatur

4   GNU Kommandos

# GNU Assembler im 64-Bit Modus
as -g -al=hello.lst -o hello.o hello.s

# Mit dem GCC eine .s Datei kompilieren im 64-Bit Modus
gcc -c hello.s

# Mit dem GCC einen C Quelltext im 32-Bit Modus nach Assembler wandeln.
# Es wird die Datei code.s erzeugt.
gcc -O2 -S -m32 code.c

# Mit dem GCC einen C Quelltext im 64-Bit Modus nach Assembler wandeln.
# Es wird die Datei code.s erzeugt.
gcc -O2 -S -m64 code.c

# Mit dem GNU Linker ld eine oder mehrere .o Dateien zu einer
# ausfuehrbaren Datei linken. Weiter .o Dateien gibt man einfach am
# Ende der Kommandozeile an.
ld -o hello hello.o