• Navigation überspringen
  • Zur Navigation
  • Zum Seitenende
Organisationsmenü öffnen Organisationsmenü schließen
Friedrich-Alexander-Universität Lehrstuhl für Informatik 4 (Systemsoftware)
  • FAUZur zentralen FAU Website
  1. Friedrich-Alexander-Universität
  2. Technische Fakultät
  3. Department Informatik
Suche öffnen
  • English
  • Campo
  • StudOn
  • FAUdir
  • Stellenangebote
  • Lageplan
  • Hilfe im Notfall
  1. Friedrich-Alexander-Universität
  2. Technische Fakultät
  3. Department Informatik
Friedrich-Alexander-Universität Lehrstuhl für Informatik 4 (Systemsoftware)
Menu Menu schließen
  • Lehrstuhl
    • Team
    • Aktuelles
    • Kontakt und Anfahrt
    • Leitbild
    • 50-jähriges Jubiläum
    Portal Lehrstuhl
  • Forschung
    • Forschungsbereiche
      • Betriebssysteme
      • Confidential Computing
      • Eingebettete Systemsoftware
      • Verteilte Systeme
    • Projekte
      • AIMBOS
      • BALu
      • BFT2Chain
      • DOSS
      • Mirador
      • NEON
      • PAVE
      • ResPECT
      • Watwa
    • Projektkampagnen
      • maRE
    • Seminar
      • Systemsoftware
    Portal Forschung
  • Publikationen
  • Lehre
    • Sommersemester 2025
      • Applied Software Architecture
      • Ausgewählte Kapitel der Systemsoftware
      • Betriebssystemtechnik
      • Projekt angewandte Systemsoftwaretechnik
      • System-Level Programming
      • Systemnahe Programmierung in C
      • Systemprogrammierung 1
      • Verteilte Systeme
    • Wintersemester 2024/25
      • Betriebssysteme
      • Middleware – Cloud Computing
      • Systemprogrammierung 2
      • Verlässliche Echtzeitsysteme
      • Virtuelle Maschinen
      • Web-basierte Systeme
    Portal Lehre
  • Examensarbeiten
  1. Startseite
  2. Extern

Extern

Bereichsnavigation: Lehre
  • Betriebssystemtechnik
    • Vorlesung
      • Folien
      • Glossar
    • Übung
      • Aufgaben
      • Dokumentation
        • Blog
          • Entwicklungsumgebung
            • Assembler Crashkurs
              • C++ Crashkurs
                • 🔗 Testrechnerverwaltung
                • Kontakt
              • Evaluation

              Blog

              Hinweise zur Implementierung der Systemaufrufschnittstelle

              Bernhard Heinloth

              2022-05-11

              Es hat sich in der Rechnerübung ein von mir nicht erwarteter Stolperstein aufgetan, vor dem ich euch hiermit bewahren will: Wenn ihr in Assembler den Einsprung für die Systemaufrufe baut, also z.B.

              [GLOBAL syscall_entry]
              ALIGN 8
              syscall_entry:
                  swapgs
                  ; ...

              und das mit IDT::handle in C++ referenzieren wollt, so müsst ihr das externe Symbol (mit C Linkage!) deklarieren:

              extern "C" void syscall_entry();

              und passend dazu irgendwo

              IDT::handle(0x80, reinterpret_cast<void*>(syscall_entry), ...

              Hier wird implizit ein Zeiger auf die Funktionsadresse verwendet, man kann aber auch explizit &syscall_entry schreiben, ist gleichwertig.

              Wenn ihr stattdessen jedoch

              extern "C" void * syscall_entry;

              schreibt, dann behauptet ihr gegenüber eurem Übersetzer, dass dies eine Speicheradresse mit einem void-Pointer (= 8 Byte groß) sei! Ein IDT::handle(0x80, syscall_entry, ... würde dadurch dann die ersten 8 Byte Maschinencode der Funktion als Zieladresse interpretieren, im Beispiel also irgendwas 0x...f8010f (weil swapgs die erste Instruktion ist und den Opcode 0f 01 f8 hat) – ein General Protection Fault ist das Resultat.

              Die einzige richtige Lösung bei dieser Deklaration wäre ein Aufruf mittels

              IDT::handle(0x80, reinterpret_cast<void*>(&syscall_entry), ...

              Hierbei unbedingt den Adressoperator & berücksichtigen!

              Weiterer Hinweis zum Bearbeiten der Aufgabe:

              Für die neuen x64 Register r8 … r15 gibt es im inline-Assembly keine schöne Lösung (nur Umkopieren oder Hacks mit expliziten Registervariablen, was eine GCC Erweiterung ist) – ich würde euch deshalb empfehlen die Syscall-Stubs direkt in NASM zu schreiben.

              Man kann da zum Beispiel hervorragend ein generisches Makro (siehe interrupt/handler.asm) für alle Syscalls bauen, dem man als Makroparameter den Syscallnamen und -nummer übergibt:

              %macro SYSSTUB 2
              [GLOBAL sys_%1]
              ALIGN 8
              sys_%1:
                  ; ...
              %endmacro
              
              
              SYSSTUB read, 1
              SYSSTUB write, 2
              SYSSTUB sleep, 3

              Das Makro ist dabei nur wenige Zeilen lang.

              Natürlich muss man dann noch eine C-Deklaration zu sys_read, sys_write, sys_sleep angeben, und es gibt keinen (mir bekannten) schönen Weg um C enums in NASM einzubauen – aber das braucht ihr gar nicht, es ist für diese Aufgabe absolut in Ordnung wenn hier an zwei Stellen (sowohl im Assembler-Stub als auch im C++-Syscallhandler) die Systemaufrufnummern definiert werden.

              Und dieser Ansatz lässt sich auch sehr einfach auf schnelle Systemaufrufe (fast_read, …) erweitern

              Zusammengefasst: Bitte seht besser von zu viel Präprozessor-Magie ab, der Code sollte wartbar und verständlich bleiben.

              Zurück zur Übersicht

              Friedrich-Alexander-Universität
              Erlangen-Nürnberg

              Schlossplatz 4
              91054 Erlangen
              • Impressum
              • Datenschutz
              • Barrierefreiheit
              • Facebook
              • RSS Feed
              • Xing
              Nach oben