# How to reduce EXE size of x86 ASM compiled with FASM?

As an exercise, I've created a simple solution for this challenge, in x86 Assembly Language. I'm running this with FASM on Windows. Here's my source code:

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'


When I compile this, I get an executable larger than I expected. Here's a hexdump:

https://pastebin.com/W5sUTvTe

I notice there's a lot of empty space between the code section and the data and library import sections, as well as a message saying "This program cannot be run in DOS mode" embedded in the code. How can I assemble my source code to a small file, suitable for Code Golf?

As a side note, suggestions for better ways to print to stdout without importing msvcrt and calling printf are welcome.

• @iBug I'm sorry to hear that. Could you please suggest a more suitable place for me to ask? – vasilescur Nov 21 '17 at 13:22
• @iBug Tips questions asking for golfing help in specific cases are most definitely not off-topic here. – AdmBorkBork Nov 21 '17 at 13:22
• Relevant meta – AdmBorkBork Nov 21 '17 at 13:25
• It has to be: start: push char Lb: call [printf] call [printf] call [printf] call [printf] inc [char] cmp [char], 'Z' jle Lb because if not, could be consume the stack; one has to see if each call to printf one has to add the instruction that adjust esp – RosLuP Nov 21 '17 at 14:55
• instead of printf, you can WriteFile(stdout), needing no imports other than kernel32 (which is present by default, you just need to determine the address) – peter ferrie Nov 24 '17 at 20:13

## 1 Answer

Quite a bit general tip, but

# Use COM file format instead of PE EXE.

PE EXE has a few flaws making the format pretty much useless in code-golf. First one is the image aligning (Windows won't run the EXE file if it's not aligned properly), and the second one is the header size. There are a few factors that aren't this important (dividing the executable into sections).

Advantages of using COM file format (that is pretty much equivalent to flat binary) are:

• Zero header code, file isn't divided into sections
• No image aligning (so the image size might not be divisible by a strictly defined power of two, but it has to be smaller than 65K. It doesn't change much though, because if your submission is larger than 65K, you're doing something wrong).
• You can't use external libraries - this is actually a plus, because you without doubt have other way to perform I/O. That's where BIOS interrupts come handy.
• You have direct control over the memory and devices linked up to the system, therefore there is no paging, no access violations, no memory protection, no concurrency, so on and so forth. These features make it easier to golf really creative programs.

I've revised your code to work as flat binary. It's dead simple:

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


The output binary is just 32 bytes big. I believe, it's possible to reduce the size even further, but this is just a starting point.

Assemble with nasm -fbin file.asm -o file.com. Note, this example has been made for NASM, but you can translate it freely to FASM, and it will work flawlessly.