How Small Can Hello World Be?

The Origin

I started thinking about small programs because I was interested in learning assembly. I learned the basics a while ago, on Windows. Recently I decided to see how Linux assembly works. I was doing some reading when I came across this page. I was already familar with small programs from reading a bit about the demoscene, but this page got me thinking, "why not try to make the smallest possible Hello World program under Linux, just to get used to the process of assembly using Linux?" So I did.

High Level Hello

When I decided to write this page, I wondered "what is the smallest Hello World I can make in a High Level language?". So immediately after writing this sentence, I went off to find out. I then realized that it would be hard to quantify size for an interperated language (i.e. Ruby, what I used). But for a sense of scale, the final Ruby file was 20 Bytes. But I want to get this show on the road, so I will move on.

The ELF Binary

I decided to use the flat assembler to assemble my programs because I was famililar with it from Windows, and because it assembles and links in one step. As my starting point, I used the included hello world ELF code. The first change I made was to switch:

  • I did this because I noticed that ebx already had the value of 0x1 in it, so exchanging would save space. This saved 4 bytes, with the final size of the ELF being 156 Bytes. The next change I made was to remove the seperate segment for declaring the message and message size. I was unsure if this would even work, and was pleased to find that it was possible, and reduced the final size to 128 Bytes. At this point I thought I was out of possible optimizations, but I was doing some reading about ELFs and came across another page. I read on, hoping I could use the starting states of the registers to optimize more. The change in the 2.2 kernel that sets the starting states to 0 looked promising, and I hoped that it held true for my kernel (3.16.0-4-amd54). To test I simply changed:

  • I expected that ebx would be set to 0x0 initially, and that I could then just increment to get the desired value, saving space. It worked, and the size was brought down to 120 Bytes. Download my source or the final program