Zpět na domů

Assembler x86-64 GUI X11 fasmg

Článek popisuje vytvoření minimálního GUI v x86-64 assembleru s X11 protokolem pomocí fasmg. Rozebírá makra pro vararg printf, systémové volání a optimalizaci struktur pro mmap. Podrobně o debug/release sestavení v VSCode a ladění v Cutter.

Minimální GUI v assembleru: X11 + fasmg optimalizace
Advertisement 728x90

Minimální GUI v assembleru x86-64 s X11: optimalizace pro fasmg

Vývojáři píšící nízkoúrovňový kód často řeší minimalizaci velikosti spustitelných souborů při zachování funkčnosti. V tomto článku si ukážeme vytvoření minimálního GUI v assembleru x86-64 s využitím protokolu X11. Použijeme fasmg pro generování kompaktního binárního souboru bez linkeru, mmap pro dynamické přidělování paměti a makra pro zjednodušení systémových volání.

Cílem je GUI okno s textem o velikosti menší než původní implementace. Zaměříme se na čitelnost kódu pro středně pokročilé a senior vývojáře: struktury požadavků X11, kompatibilita ABI, optimalizace kopírování dat.

Příprava vývojového prostředí

Sestavení v VSCode s úlohami pro release a debug režimy. Release: DEBUG=0, debug: DEBUG=1 s generováním DWARF symbolů.

Google AdInline article slot
{
    "label": "Vytvořit release spustitelný soubor",
    "type": "shell",
    "command": "chmod",
    "args": ["+x", "${fileBasenameNoExtension}"],
    "dependsOn": "Release sestavení s fasmg"
}

Ladění v Cutter s launch.json:

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

Klávesa Ctrl+Shift+T pro debug sestavení (.asm soubory).

Makra pro ladění a logování

Připojíme libc dynamicky pouze v debug:

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

Makra pro vararg printf s podporou %d, %f, %e, %g, %a. COUNT_ARGS_TO počítá argumenty, GET_VARARG_TO extrahuje podle indexu.

Konverze float/double do IEEE-754 přes virtuální paměť fasm:

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

Hlavní makro VARG_FUNC parsuje formátovací řetězec, rozděluje argumenty do registrů podle System V ABI (xmm0-xmm7 pro float, rsi/rdx/... pro integer). DEBUG_MSG je obálka pro logy.

Google AdInline article slot

Struktury X11 požadavků

Jednotná struktura FULL_LAYOUT obsahuje všechny potřebné požadavky:

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

Pole jsou uspořádána pro minimalizaci kódu kopírování. Rozložení v r12, sokety v r13+.

Univerzální makro systémových volání

MAKE_SYSCALL automatizuje nastavení registrů (rdi, rsi, rdx, r10, r8, r9) s podporou 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
        ; analogicky pro rsi, rdx, r10...
    end iterate
    ; syscall scall
end macro

Optimalizace velikosti a výkonu

  • mmap místo statických dat: 4KB stránka pro všechny struktury X11.
  • movsb pro kopírování: seskupení polí minimalizuje volání.
  • Registry pro konstanty: r12-r15 se nemění.
  • Výchozí hodnoty v binárním souboru: makra generují pouze použité pole.
  • Pevné písmo: X11 automaticky volí "fixed".

Výhody fasmg: kompaktní kód, makra, absence linkeru.

Co je důležité

  • Struktury X11 požadavků jsou uspořádány pro optimální movsb kopírování.
  • Vararg printf makro s IEEE-754 konverzí přes virtuální paměť.
  • Univerzální syscall makro snižuje boilerplate o 70 %.
  • mmap 4KB pokrývá všechny struktury bez statických dat v binárním souboru.
  • Debug/release sestavení v VSCode + Cutter pro reverzní inženýrství.

— Editorial Team

Advertisement 728x90

Číst dál