Hello World optimised for size

My neice said she was learning to program in Rust and enjoying it very much, so I just tried compiling a Hello World which generated a really fat executable file. There must be a better way to optimise the size, but I couldn't get a working file below 128,000 bytes. You will see the 9,728 byte executable below however this aborted while trying to load a DLL.

I also Checked C, ASM, various Pascals, and my guilty favourite: PureBasic. Clearly PureBasic is superior to all other high level languages based on this ridiculous test.

The first Microsoft ASM code used an external library to display text and then linked this into the executable via gcc which produced to some bloating. I later found MASM (2) code that called the kernel directly which produced a more compact executable file. Then there is the amazing FASM compiler: we have a new winner for smallest executable. The first FASM code is 32 bit using an include file to reference calls to the OS, while the second FASM example has taken a completely spelled out route but is also 64 bit. I noted that the executable files produced are mostly zeros, so while these might seem to be good candidates for executable compression using something like FileOptmizer, the added decompression code would likely inflate the final file size(?) so FileOptimizer did nothing.

Don't be fooled by Turbo Pascal 7, which may have produced a tiny EXE but it is 16 bit, meaning you can't easily run it in the standard command prompt under modern windows, you should get DOSBox or similar. The same goes for the .COM file produced by Turbo Pascal 3 ... which is also bloated due to the inclusion of TP3's complete library, as wonderfully small as that is.

Seriously though: bloat sucks.

RUST

fn main() { println!("Hello world 2023-12-31") }
rustc HelloWorld.rs
  148,480 HelloWorld.exe
1,339,392 HelloWorld.pdb
       51 HelloWorld.rs

rustc -C opt-level=z -C lto -C codegen-units=1 -C panic=abort HelloWorld.rs
  128,000 HelloWorld.exe
1,421,312 HelloWorld.pdb

rustc -C opt-level=s -C prefer-dynamic -C target-feature=-crt-static HelloWorld.rs
    9,728 HelloWorld.exe 
1,421,312 HelloWorld.pdb
NOTE: Tries to load external DLL - halts if not found.

C

#include <stdio.h> int main() { printf("Hello World 2023-12-23"); return 0; }
cl HelloWorld.c /out:HelloWorld_ms.exe
     85 HelloWorld.c
142,848 HelloWorld_ms.exe

bcc32c HelloWorld.c -o HelloWorld_bcc.exe
 62,464 HelloWorld_bcc.exe

gcc HelloWorld.c -s -o HelloWorld_gcc.exe
 42,496 HelloWorld_gcc.exe

PureBasic

If OpenConsole() PrintN ("Hello World 2023-12-31") EndIf
6,656 HelloWorld.exe
  431 HelloWorld.pb

Turbo Pascal 3

BEGIN Writeln('Hello World 1986-05-02'); END.
11,259 HELLOW.COM
    37 HELLOW.PAS

Turbo Pascal 7

BEGIN Writeln('Hello World 1993-02-01'); END.
2,192 HELLOW.EXE
   36 HELLOW.PAS

Lazarus / FreePascal

program HelloWorld; begin Writeln('Hello World 2024-01-02'); end.
155,267 HelloWorld.exe
  1,797 HelloWorld.lpi
    101 HelloWorld.lpr
  1,129 HelloWorld.lps

Project > Project Options 
    > Run uses the debugger : unticked
    > Generate info for the debugger : unticked
 50,176 HelloWorld.exe

Delphi 11 Community

program HelloWorld; {$APPTYPE CONSOLE} begin Writeln ('Hello World 2024-01-03'); end.
Original code uses sysutils, default compiler settings
1,381,248 HelloWorld.exe

Above code, default compiler settings
  270,065 HelloWorld.exe

Project > Options > Compiling > Debugging : none/false
  166,637 HelloWorld.exe

Project > Options > Linking > Debug Information : false
   49,152 HelloWorld.exe

MASM (1)

extrn printf:proc extrn exit:proc .data hello db 'Hello world! 2024-01-02',0ah,0 .code main proc mov rcx,offset hello sub rsp,20h call printf add rsp,20h mov rcx,0 call exit main endp end
ml64 HelloWorld.asm /c
    779 HelloWorld.asm
    584 HelloWorld.obj

gcc -m64 HelloWorld.obj -o HelloWorld.exe
117,030 HelloWorld.exe

gcc -m64 HelloWorld.obj -s -o HelloWorld.exe
 16,896 HelloWorld.exe

MASM (2)

includelib kernel32.lib GetStdHandle proto WriteConsoleA proto ExitProcess proto .data msg byte "Hello World 2024-01-04", 0Ah, 0Dh stdout qword ? .code main proc sub rbp, 40 mov rcx, -11 call GetStdHandle mov stdout, rax mov rcx, stdout lea rdx, msg mov r8, lengthof msg call WriteConsoleA add rbp, 40 mov rcx, 0 call ExitProcess main endp end
ml64 helloworld_masm.asm /link /subsystem:console /entry:main
  512 HelloWorld_masm.asm
2,560 helloworld_masm.exe
  835 helloworld_masm.obj

FASM (1)

format PE console ; 32Bit include 'win32ax.inc' .code start: invoke WriteConsole,\ <invoke GetStdHandle,STD_OUTPUT_HANDLE>,\ "Hello World 2024-01-03",\ 22,0 call [ExitProcess] .end start
  203 HelloWord_fasm1.ASM
1,536 HelloWord_fasm1.EXE

FASM (2)

format pe64 console ; 64Bit entry start STD_OUTPUT_HANDLE = -11 section '.text' code readable executable start: sub rsp,8*7 ; reserve stack (API), stack dqword align mov rcx,STD_OUTPUT_HANDLE call [GetStdHandle] mov rcx,rax lea rdx,[message_txt] mov r8d,message_len lea r9,[rsp+4*8] mov qword[rsp+4*8],0 call [WriteFile] mov ecx,eax call [ExitProcess] section '.data' data readable writeable message_txt db 'Hello World! 2024-01-03',0 message_len = $ - message_txt section '.idata' import data readable writeable dd 0,0,0,RVA kernel_name,RVA kernel_table dd 0,0,0,0,0 kernel_table: ExitProcess dq RVA _ExitProcess GetStdHandle dq RVA _GetStdHandle WriteFile dq RVA _WriteFile dq 0 kernel_name db 'KERNEL32.DLL',0 user_name db 'USER32.DLL',0 _ExitProcess db 0,0,'ExitProcess',0 _GetStdHandle db 0,0,'GetStdHandle',0 _WriteFile db 0,0,'WriteFile',0
  932 HelloWorld_fasm2.asm
2,048 HelloWorld_fasm2.exe