Zurück zur Startseite

Assembler x86-64 GUI X11 fasmg

Artikel beschreibt das Erstellen einer minimalen GUI auf x86-64-Assembler mit X11-Protokoll unter Verwendung von fasmg. Makros für vararg printf, Systemaufrufe und Strukturoptimierung für mmap werden besprochen. Details zu Debug-/Release-Build in VSCode und Debugging in Cutter.

Minimale GUI auf Assembler: X11 + fasmg-Optimierung
Advertisement 728x90

Minimale GUI in x86-64-Assembler mit X11: Optimierung für fasmg

Entwickler von Low-Level-Code stehen oft vor der Herausforderung, die Größe der ausführbaren Datei zu minimieren, ohne die Funktionalität einzuschränken. Dieser Artikel zeigt, wie man eine minimale GUI in x86-64-Assembler mit dem X11-Protokoll erstellt. Wir nutzen fasmg, um eine kompakte Binärdatei ohne Linker zu generieren, mmap für dynamische Speicherzuweisung und Makros zur Vereinfachung von Systemaufrufen.

Das Ziel ist ein GUI-Fenster mit Text, das kleiner ist als ursprüngliche Implementierungen. Der Fokus liegt auf der Lesbarkeit des Codes für mittlere bis erfahrene Entwickler: X11-Anforderungsstrukturen, ABI-Kompatibilität und Optimierung der Datenkopie.

Einrichtung der Entwicklungsumgebung

Erstellen Sie in VSCode mit Tasks für Release- und Debug-Modi. Release: DEBUG=0, Debug: DEBUG=1 mit DWARF-Symbolgenerierung.

Google AdInline article slot
{
    "label": "Release-Executable erstellen",
    "type": "shell",
    "command": "chmod",
    "args": ["+x", "${fileBasenameNoExtension}"],
    "dependsOn": "Release-Build mit fasmg"
}

Debugging in Cutter mit launch.json:

{
    "name": "Cutter starten",
    "type": "node",
    "request": "launch",
    "preLaunchTask": "Debug-Build mit fasmg",
    "runtimeExecutable": "Cutter.AppImage",
    "runtimeArgs": [
        "${fileDirname}/${fileBasenameNoExtension}",
        "--analysis", "2",
        "--arch", "x86",
        "--bits", "64"
    ]
}

Drücken Sie Strg+Umschalt+T für Debug-Builds (.asm-Dateien).

Makros für Debugging und Protokollierung

Dynamisches Verknüpfen von libc nur im Debug-Modus:

Google AdInline article slot
include 'dynamic/import64.inc'
if DEBUG
    interpreter '/lib64/ld-linux-x86-64.so.2'
    needed 'libc.so.6'
    import printf
end if

Makros für vararg printf mit Unterstützung für %d, %f, %e, %g, %a. COUNT_ARGS_TO zählt Argumente, GET_VARARG_TO ruft sie nach Index ab.

Konvertieren von Float/Double zu IEEE-754 über fasm virtuellen Speicher:

macro MOVQ_IMM reg, val
    local bits
    virtual at 0
        dq val
        load bits qword from 0
    end virtual
    mov rax, bits
    movq reg, rax
end macro

Das Haupt-VARG_FUNC-Makro analysiert den Formatstring und verteilt Argumente auf Register gemäß System V ABI (xmm0-xmm7 für Float, rsi/rdx/... für Integer). DEBUG_MSG ist ein Wrapper für Protokolle.

Google AdInline article slot

X11-Anforderungsstrukturen

Eine vereinheitlichte FULL_LAYOUT-Struktur enthält alle notwendigen Anforderungen:

struct FULL_LAYOUT
    ridBase             dd  0
    ridMask             dd  0
    windowRootId        dd  0
    rootVisualId        dd  0
    gcId                dd  0
    exposed             db  0
    create_window_req   X11_CREATE_WINDOW
    draw_string_req     STRING_TO_DRAW
    handshake           X11_HANDSHAKE
    gc_request          X11_CREATE_GC
    addr_un             SOCKADDR_UN
    map_window_req      X11_MAP_WINDOW
    union
        free    rb     HEAP_SIZE - ($ - create_window_req)
        setup   X11_SETUP
        pollfd  POLLFD
    endu
ends

Felder sind geordnet, um Kopiercode zu minimieren. Layout in r12, Sockets in r13+.

Universelles Systemaufruf-Makro

MAKE_SYSCALL automatisiert das Setzen von Registern (rdi, rsi, rdx, r10, r8, r9) mit Unterstützung für ptr [c], [c], 0:

macro MAKE_SYSCALL scall, args&
    iterate arg, args
        if % = 1
            match =ptr [c], arg
                lea    rdi, [c]
            else match [c], arg
                mov     rdi, [c]
            else match =0, arg
                xor    rdi, rdi
            else
                mov    rdi, arg
            end match
        ; ähnlich für rsi, rdx, r10...
    end iterate
    ; syscall scall
end macro

Größen- und Leistungsoptimierungen

  • mmap statt statischer Daten: 4KB-Seite für alle X11-Strukturen.
  • movsb zum Kopieren: Gruppieren von Feldern minimiert Aufrufe.
  • Register für Konstanten: r12-r15 bleiben unverändert.
  • Standardwerte in Binärdatei: Makros generieren nur genutzte Felder.
  • Feste Schriftart: X11 wählt automatisch "fixed".

Vorteile von fasmg: kompakter Code, Makros, kein Linker.

Wichtige Erkenntnisse

  • X11-Anforderungsstrukturen sind für optimale movsb-Kopie geordnet.
  • Vararg printf-Makro mit IEEE-754-Konvertierung über virtuellen Speicher.
  • Universelles Syscall-Makro reduziert Boilerplate um 70 %.
  • mmap 4KB deckt alle Strukturen ohne statische Daten in der Binärdatei ab.
  • Debug/Release-Builds in VSCode + Cutter für Reverse Engineering.

— Editorial Team

Advertisement 728x90

Weiterlesen