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