HelloAssembly: The smallest possible complete Windows application (2021)

github.com

89 points by Bluestein 2 days ago


https://www.youtube.com/watch?v=b0zxIfJJLAY

ntstatusquo - 2 days ago

You can get a sub 20kb executable with C in MSVC and no weird tricks, i.e. just setting a particular combination of compiler/linker flags, like /NODEFAULTIB, /MERGE, /FILEALIGN:512 etc. Small enough that it's basically nothing, downloads in a couple of seconds over 56k dialup, and you get to use normal tooling. This is the compromise that makes the most sense to me, for products you're actually shipping. If you want to try out the nocrt approach, honestly the LLMs do a fine job of writing you some replacements for the parts of the crt that you likely want i.e. memcpy/memcmp/strlen helpers, with x64/arm64 SIMD and all.

Set /HEAP:4096,4096 and /STACK:65536,4096, write yourself a simple 100 line growable arena implementation, use that, avoid the heap entirely. Very quick and easy way to get a real windows program up and running that uses about 500kb of commit at baseline.

You end up with only ntdll.dll, kernelbase.dll, and kernel32.dll loaded. Trying to eliminate any of these becomes pretty painful and you venture into the territory of weird tricks that are expensive to maintain.

Dave's approach is a fun exercise though.

delta_p_delta_x - 2 days ago

Interesting to bypass CRT and work directly against the Windows API. That said, these rely on USER.32.DLL and KERNEL32.DLL to do the majority of the heavy lifting.

It's a bit like 'smallest hello world in assembly' but the code is just setting up the calling convention and then passing the zero-terminated character string into `write`. Cool, but that could be done a bit more straightforwardly in C, too. A lot of assembly (including in the linked repository) is book-keeping for the platform's calling convention.

rfgplk - 2 days ago

"smallest possible" is exactly one instruction; possibly 0xc3 [ret] or 0x90 [nop]; the problem lies in how you define "complete Windows application", because the answer really differs depending on if you want to make it ABI compliant. But there's nothing preventing you from creating a custom loader/executor that reads a pure binary file, maps it as exec and runs it.

WillAdams - 2 days ago

For more of the same (though I wish source was available) which actually does something useful, see the various small utilities at

https://www.grc.com/freepopular.htm

Dwedit - a day ago

I made my own 64-byte MS-DOS stub that uses a shorter message "Win32 Only!" instead of the usual "This program can only be run in DOS mode" message. By using the shorter stub, using the secret flag to omit the Rich header, and possibly merging sections together, I can usually get the PE header to fit within 512 bytes, and the linker won't pad out the PE header to 1024 bytes.

A copy can be found at https://github.com/Dwedit/NoCopilotKey/blob/main/stub.bin

haunter - 2 days ago

Meanwhile in the Unix world you can go as low as 45 bytes https://www.muppetlabs.com/~breadbox/software/tiny/teensy.ht...

abcd_f - 2 days ago

The smallest meaningful program for MS-DOS was exactly 2 bytes:

  FA F4
That's CLI HLT, which effectively deadlocked the machine. Had to be saved as a .com fule obviously, not as an .exe.
ggerules - 2 days ago

Windows and assembly is a fun topic!

Putting the search terms "Windows" and "assembly language" turns up all sort of books. The one that got me to initially explore the topic (from 1993).... [0]

For a more up to date treatment of assembly and windows.... comes with source code for the IDE also. Ray Seyfarth's book [1].

[0] Windows Assembly Language & Systems Programming: Object Oriented & Low-Level Systems Programming in Assembly Language for Windows 3.X

[1] Introduction to 64 Bit Windows Assembly Language Programming: Fourth Edition ISBN-13: 978-1543138849, ISBN-10: 1543138845

eggy - 2 days ago

I should try FASM to see if it produces a smaller size exe. COM files are small, but 16-bit DOS was the thing back in the day - 100H yeah and basically a memory dump.

iamthejuan - 19 hours ago

When I hear assembly, two people always comes into my mind, Chris Sawyer and Steve Gibson.

p0w3n3d - 2 days ago

Looks too kinky for me. WinAPI + C - okay. But not this

hnea3ekp5i - 2 days ago

Appreciate you writing it up

drdexebtjl - 2 days ago

[flagged]

taf2 - 2 days ago

love this and it's timely as I think with AI more of my code will just be native assembly for example: https://github.com/taf2/tic-tac-toe my m series native assembly based tic tac toe windowed game... very portable too you just simply execute codex --yolo port my app to x y z host...