Як зменшити розмір EXE x86 ASM, складеного за допомогою FASM?


14

Як вправу я створив просте рішення для цього завдання, мовою асамблеї x86. Я запускаю це з FASM в Windows. Ось мій вихідний код:

format PE console
entry start

include 'WIN32A.inc'

section '.text' code executable
start:
    push    char            ; Start at 'A'
    call    [printf]        ; Print the current letter 4 times
    call    [printf]
    call    [printf]
    call    [printf]
    inc     [char]          ; Increment the letter
    cmp     [char], 'Z'     ; Compare to 'Z'
    jle     start           ; char <= 'Z' --> goto start

section 'r.data' data readable writeable
    char    db  'A', 10, 0  ; Stores the current letter

section '.idata' data readable import
    library  msvcrt,   'msvcrt.dll'
    import   msvcrt, printf, 'printf'

Коли я компілюю це, я отримую виконуваний файл більший, ніж я очікував. Ось шістнадцятковий набір:

https://pastebin.com/W5sUTvTe

Я зауважую, що між розділом коду та розділами імпорту даних та бібліотеки є багато порожнього простору, а також повідомлення про те, що "Ця програма не може бути запущена в режимі DOS", вкладена в код. Як я можу зібрати свій вихідний код до невеликого файлу, який підходить для Code Golf?

Як зауваження, вітаються пропозиції щодо кращих способів друку stdoutбез імпорту msvcrtта дзвінків printf.


@iBug Вибачте, що це чую. Не могли б ви запропонувати мені більше відповідне місце?
vasilescur

12
@iBug Поради щодо запитань про допомогу в гольфі в конкретних випадках тут, безумовно, не є темою.
AdmBorkBork


1
Це повинно бути: start: push char Lb: call [printf] call [printf] call [printf] call [printf] inc [char] cmp [char], 'Z' jle Lb, оскільки якщо ні, то можна споживати стек ; треба побачити, чи потрібно до кожного дзвінка до printf додавати інструкцію, яка коригує esp
RosLuP

1
замість printf ви можете написати WriteFile (stdout), не потребуючи імпорту, крім kernel32 (який за замовчуванням присутній, вам просто потрібно визначити адресу)
peter ferrie

Відповіді:


2

Досить загальна порада, але

Використовуйте формат файлу COM замість PE EXE.

У PE EXE є кілька недоліків, що робить формат в значній мірі марним у коді-гольфі. Перший - вирівнювання зображення (Windows не запустить файл EXE, якщо він неправильно вирівняний), а другий - розмір заголовка. Є кілька факторів, які не так важливі (поділ виконуваних файлів на розділи).

Переваги використання формату файлів COM (що майже еквівалентно плоскому двійковому):

  • Нульовий код заголовка, файл не розділений на розділи
  • Ніякого вирівнювання зображення (тому розмір зображення не може бути розділений за суворо визначеною потужністю в два, але він повинен бути меншим, ніж 65 К. Хоча це не сильно змінюється, тому що якщо ваше подання більше 65 К, ви робите щось не так).
  • Ви не можете використовувати зовнішні бібліотеки - це насправді плюс, оскільки у вас, без сумніву, є інший спосіб виконати введення / виведення. Ось тут і стане в нагоді переривання BIOS .
  • Ви маєте прямий контроль над пам’яттю та пристроями, підключеними до системи, тому немає жодних підказок, жодних порушень доступу, захисту пам’яті, не одночасності тощо. Ці функції полегшують гольф по-справжньому творчих програм.

Я переглянув ваш код, щоб він працював як плоский двійковий код. Це мертво просто:

ORG 100H

MOV DX, P
MOV AH, 9

L:
    INT 21H
    INT 21H
    INT 21H
    INT 21H

    INC BYTE [P]
    CMP BYTE [P], 'Z'
    JLE L

MOV AX, 4C00h
INT 21h

P DB "A", 10, "$"

Вихідний двійковий файл складає всього 32 байти. Я вважаю, що можливо зменшити розмір ще більше, але це лише вихідний момент.

Зберіть з nasm -fbin file.asm -o file.com. Зауважте, цей приклад зроблений для NASM, але ви можете вільно перекласти його на FASM, і він буде працювати бездоганно.


Не можу повірити, що я відповів на це питання і повернувся до нього з google
Krzysztof Szewczyk
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.