[HN Gopher] The smallest Hello World program
___________________________________________________________________
The smallest Hello World program
Author : michidk
Score : 50 points
Date : 2024-12-30 16:23 UTC (3 days ago)
(HTM) web link (blog.lohr.dev)
(TXT) w3m dump (blog.lohr.dev)
| mrfinn wrote:
| These challenges are funny - they remind me of the old days. Back
| in the DOS/Windows days, we used to have the .com format, which
| was perfect for tiny programs. One could even write a program of
| less than 10 bytes that could actually do something!
|
| We've come a long way since then, and is like, at some point,
| nobody cared about optimizing executable size anymore
| xpasky wrote:
| JMP FFFF:0000
| mrfinn wrote:
| INT 13h... uff chills
| secondcoming wrote:
| People in the embedded space care. Symbian OS was compiled for
| small size, only certain parts were allowed use O3, such as the
| jpeg decoder.
| hinkley wrote:
| I learned to write COM programs at some point but quickly
| unlearned it. There were some spots where you can use them and
| not .bat files, but outside of that it's a lot.
| theandrewbailey wrote:
| Some people care about executable size, (mostly) everyone else
| ships Electron apps.
| smokel wrote:
| debug -a 100 178A:0100 int 19 178A:0102
| -r cx CX 0000 :2 -n reboot.com -w
| Writing 00002 bytes -q
| gr33kdude wrote:
| Linking a similar, very popular past example of this: Teensy:
| https://www.muppetlabs.com/~breadbox/software/tiny/teensy.ht...
| xpasky wrote:
| Now, can we make it even smaller applying
| https://nathanotterness.com/2021/10/tiny_elf_modernized.html ? We
| shouldn't need the full ELF header...
| xpasky wrote:
| Oh it has been done:
| https://nathanotterness.com/2021/10/hello_105.asm
| bd01 wrote:
| This is pretty bad. Let's start with the very first instruction:
| mov rax, 1
|
| An actual "mov rax, 1" would assemble to 48 B8 01 00 00 00 00 00
| 00 00, a whopping TEN bytes.
|
| nasm will optimize this to the equivalent "mov eax, 1", that's 6
| bytes, but still: xor eax, eax ; 2 bytes
| inc eax ; 2 bytes
|
| would be much smaller. Second line: mov rdi, 1
|
| You already have the value 1 in eax, so a "mov edi, eax" (two
| bytes) would suffice. Etc. etc.
| xpasky wrote:
| push 1 pop rax
|
| is even shorter (credit: https://old.reddit.com/r/programming/c
| omments/q6mnz1/what_is...)
| rep_lodsb wrote:
| Linux initializes all general purpose registers to zero. It's
| not documented AFAIK, but should be reliable - it has to init
| them to _some_ value anyway to avoid leaking kernel state. So
| you can get away with: mov al,1
| ;write mov edi,eax ;handle=stdout mov
| esi,msg ;assumes load address below 4G mov
| dl,msg.len syscall mov al,60 ;assuming
| syscall succeeded, EAX was bytes written xor
| edi,edi syscall
|
| The load address stays constant unless there's some magic GNU
| extension header to enable ASLR. If we could get the code
| loaded below 64K, we could save another byte by using SI
| instead of ESI; however this doesn't work by default, you'd
| have to run 'echo 0 > /proc/sys/vm/mmap_min_addr' as root
| first.
| bd01 wrote:
| Initial register state is documented to be undefined except
| for rbp, rsp and rdx [1].
|
| Can you say for certain that no other Linux version _ever_
| used GPRs to pass something else?
|
| [1] System V ABI, page 29 (last line) and 30,
| https://refspecs.linuxbase.org/elf/x86_64-abi-0.99.pdf
| rep_lodsb wrote:
| For certain? No, but I wouldn't expect it. Not sure what
| that function pointer in rdx is intended for, but Linux
| doesn't use it.
|
| (Note for pedants: rsp is _technically_ a "general purpose
| register", but of course it is initialized to point to the
| userspace stack instead of zero.)
| retrac wrote:
| Assuming it is initial zero inc eax
|
| is a byte shorter than mov al, 1
| rep_lodsb wrote:
| Yes, but only in 32 bit mode. Not that it matters, except
| for the hypothetical future processor or Linux kernel that
| is no longer compatible with that :)
| smokel wrote:
| My favorite language for implementing short Hello World programs
| in is HQ9+ [1].
|
| Joking aside, this page [2] used to be a great tutorial on
| writing small ELF binaries, but I'm not sure whether it will
| still work in 64-bit land. It proved very helpful for writing a
| 4K intro back in 1999.
|
| [1] https://esolangs.org/wiki/HQ9%2B
|
| [2]
| https://www.muppetlabs.com/~breadbox/software/tiny/teensy.ht...
| whynotmaybe wrote:
| Could a script be a program?
|
| Because it would be much smaller in a bat file than contains :
|
| echo Hello World!
| hinkley wrote:
| Include the shebang but it's still crazy how big minimal
| programs are.
| theandrewbailey wrote:
| For the purposes of this challenge, no.
|
| > Let's first establish some rules for our 'Hello World'
| program:
|
| > It should be able to execute directly without passing to any
| other programs first (so no decompression)
|
| > It should be a 'proper' executable binary according to the
| spec
| oneshtein wrote:
| The smallest "hello, world" programs in Rust I did for Arduino
| are 294 bytes for blink and 388 bytes for hw.
| Tepix wrote:
| Here's a tiny DOS COM file that does it in 18 bytes:
| ;; 18 bytes DB 'HELLO_WOIY<$' ; executes as machine
| code, returning SP to original position without overwriting
| return address mov dx, si ; mov dx,0100h MS-
| DOS (all versions), FreeDOS 1.0, many other DOSes xchg
| ax, bp ; mov ah,9 MS-DOS 4.0 and later, and FreeDOS 1.0
| int 21h ret
|
| (credits: https://stackoverflow.com/questions/72635031/assembly-
| hello-...)
| rep_lodsb wrote:
| Well, it prints something that is the same length as the
| correct message at least.
| 5- wrote:
| here's an 80 byte x86_64 linux 'hello world' (okay, not 'Hello
| world!'). convert to binary with xxd -r -p:
| 7f454c46488d3537000000ffc7b20eeb03003e00
| b001eb1a01000000050000001800000000000000
| 1800000005000000b03c0f05ebfa380001006865
| 6c6c0000010068656c6c00006f20776f726c640a
|
| i'm sure this can be improved -- but i could never get any x86_64
| linux elf to under 80 bytes. see if you can fit the exclamation
| point still.
___________________________________________________________________
(page generated 2025-01-02 23:00 UTC)