Wie kann man die mit FASM kompilierte EXE-Größe von x86-ASM reduzieren?

14

Als Übung habe ich eine einfache Lösung für diese Herausforderung in x86-Assemblersprache erstellt. Ich führe dies mit FASM unter Windows aus. Hier ist mein Quellcode:

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'

Wenn ich dies kompiliere, erhalte ich eine ausführbare Datei, die größer ist als erwartet. Hier ist ein Hexdump:

https://pastebin.com/W5sUTvTe

Ich stelle fest, dass zwischen dem Codeabschnitt und den Daten- und Bibliotheksimportabschnitten viel Leerraum vorhanden ist und dass im Code die Meldung "Dieses Programm kann nicht im DOS-Modus ausgeführt werden" eingebettet ist. Wie kann ich meinen Quellcode zu einer kleinen Datei zusammenstellen, die für Code Golf geeignet ist?

Als Randnotiz sind Vorschläge für bessere Druckmöglichkeiten stdoutohne Importieren msvcrtund Aufrufen printfwillkommen.

Vasilescur
quelle
@iBug Es tut mir leid, das zu hören. Könnten Sie mir bitte einen passenderen Ort für Ihre Anfrage vorschlagen?
Vasilescur
12
@iBug Tips Fragen, die in bestimmten Fällen nach Hilfe beim Golfen fragen, sind hier definitiv nicht unangebracht .
AdmBorkBork
12
Relevantes Meta
AdmBorkBork
1
Es muss sein: start: push char Lb: call [printf] call [printf] call [printf] call [printf] inc [char] cmp [char], 'Z' jle Lb denn wenn nicht, könnte der Stack verbraucht werden ; man muss sehen, ob bei jedem Aufruf von printf die Anweisung hinzugefügt werden muss, die esp
RosLuP 21.11.17
1
Anstelle von printf können Sie WriteFile (stdout) verwenden. Sie müssen lediglich kernel32 importieren (standardmäßig müssen Sie nur die Adresse ermitteln)
Peter Ferrie

Antworten:

2

Ganz allgemeiner Tipp, aber

Verwenden Sie das COM-Dateiformat anstelle von PE EXE.

PE EXE hat einige Fehler, die das Format im Code-Golf so gut wie unbrauchbar machen. Das erste ist die Bildausrichtung (Windows führt die EXE-Datei nicht aus, wenn sie nicht richtig ausgerichtet ist), und das zweite ist die Headergröße. Es gibt einige Faktoren, die nicht so wichtig sind (Unterteilen der ausführbaren Datei in Abschnitte).

Die Verwendung des COM-Dateiformats bietet folgende Vorteile:

  • Null-Header-Code, Datei ist nicht in Abschnitte unterteilt
  • Keine Bildausrichtung (daher ist die Bildgröße möglicherweise nicht durch eine genau definierte Potenz von zwei teilbar, sie muss jedoch kleiner als 65 KB sein. Es ändert sich jedoch nicht viel, da Sie dies tun, wenn Ihre Übermittlung größer als 65 KB ist.) etwas stimmt nicht).
  • Sie können keine externen Bibliotheken verwenden - dies ist eigentlich ein Plus, da Sie ohne Zweifel andere Möglichkeiten haben, E / A durchzuführen. Hier bieten sich BIOS-Interrupts an.
  • Sie haben die direkte Kontrolle über den Speicher und die Geräte, die mit dem System verbunden sind. Daher gibt es kein Paging, keine Zugriffsverletzungen, keinen Speicherschutz, keine Parallelität usw. Diese Funktionen erleichtern das Golfen von wirklich kreativen Programmen.

Ich habe Ihren Code überarbeitet, um als Flat Binary zu arbeiten. Es ist ganz einfach:

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, "$"

Die Ausgabe-Binärdatei ist nur 32 Byte groß. Ich glaube, es ist möglich, die Größe noch weiter zu reduzieren, aber dies ist nur ein Ausgangspunkt.

Zusammenbauen mit nasm -fbin file.asm -o file.com. Beachten Sie, dass dieses Beispiel für NASM erstellt wurde, Sie es jedoch frei in FASM übersetzen können und es einwandfrei funktioniert.

Krzysztof Szewczyk
quelle
Ich kann nicht glauben, dass ich diese Frage beantwortet und von google
Krzysztof Szewczyk