Mar 5, 2010

Hello world in 63 bytes

I recently discovered this guide here to making teeny programs in Linux. I thought it was pretty neat, so I've decided to post their Hello world application here:
BITS 32
org 0x05430000

; ELF header stuff - this stuff is information about the executable that
; Linux uses to see how to execute it. It's stuff like what platform it's
; for, what type of executable it is (object code, executable, shared object),
; how long the program is, where the entry point is, etc.
ehdr:
; db means put a byte, dw means put a word (2 bytes)
; and dd means put a double-word (4 bytes)
db 0x7F, "ELF"
dd 1
dd 0
dd $$ ; I'm assuming that $$ means the start of the program
dw 2
dw 3
dd _start
dw _start - $$

; the program
_start:
; send the string to stdout
; system call for write is 4, file descriptor for stdout is 1
; so set eax = 4, ebx = 1, and ecx = string pointer, edx = string length
inc ebx
add eax, dword 4
mov ecx, msg
mov dl, 14
int 0x80
; quit
and eax, 0x10020
xchg eax, ebx
int 0x80

; Note: The original version doesn't put an ! at the end,
; which makes my version one byte longer. Oh well.
msg: db 'Hello, world!', 10
You can assemble this using NASM:
sudo apt-get install nasm
nasm -f bin -o a.out helloworld.asm
chmod +x a.out
It's neat because by looking at how this stuff works, you begin to understand how the operating system manages loading programs under the hood. If you're interested in this type of thing, check it out!

I'm not sure how well it would work in Mac or Windows, since a lot of the short-ness of the program comes from exploiting the fact that Linux ignores a lot of the ELF header info, if the ELF header info is too short it will pad the rest with zeroes, and finally Linux clears all registers to zero when loading a program. I'm not sure if the Windows or BSD kernels would do the same, I guess the only way to find out is to try it!

No comments: