Rendered at 20:16:59 GMT+0000 (Coordinated Universal Time) with Cloudflare Workers.
ntstatusquo 1 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.
Dwedit 22 hours ago [-]
Then you load User32.dll, and you get 2MB of commit and 1MB of private bytes. Throw in a Message Box, and it's 272KB more private bytes and 388K more commit.
Windows 10 makes it literally impossible to write something that uses low memory and uses an actual window.
ntstatusquo 41 minutes ago [-]
True, the project where I used the approach above was a TUI, so windows terminal sort of eats the impact of stuff like user32 and dwrite for you.
One trick I know of to make user32 a bit more lightweight is to call ImmDisableIme prior to creating your first window. This disables a lot of the TSF integration, which is notably quite slow. Not sure if it impacts memory footprint but worth a try. It of course does what the name says and disables IME support, so not a viable option if you have users who need IME
delta_p_delta_x 1 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.
skrellm 1 days ago [-]
> That said, these rely on USER.32.DLL and KERNEL32.DLL to do the majority of the heavy lifting.
Since the low-level Windows kernel API is undocumented and non-public, using these system DLLs is your only option on Windows.
It's just like linking against libc.so on any POSIX systems.
Pannoniae 1 days ago [-]
no, you can also call ntdll (or even syscalls although those aren't stable), there's plenty of documentation on the internet
but also why would you, not much point except for very niche functionality
skrellm 1 days ago [-]
> no, you can also call ntdll (or even syscalls although those aren't stable), there's plenty of documentation on the internet
I mean officially. Yes, you can find some on the internet, but nothing on the official MSDN.
> but also why would you, not much point except for very niche functionality
Exactly. Using system DLL API is backward and forward compatible, and just as standardized and well-documented as the POSIX API. I see no problem relying on it.
(Sidenote: as a bonus, MSDN is surprisingly good, understandable, well organized, lots of examples. I rarely say this, but well done MS, that's how a dev doc should be.)
Someone 1 days ago [-]
>> no, you can also call ntdll (or even syscalls although those aren't stable), there's plenty of documentation on the internet
> I mean officially. Yes, you can find some on the internet, but nothing on the official MSDN.
I still don't get it, what's wrong with using the user32 and kernel32 APIs? It's stable, well-documented, and is the official API on Windows. So why not use it?
> If the call to this function occurs in user mode, you should use the name "NtMapViewOfSection" instead of "ZwMapViewOfSection".
munchler 1 days ago [-]
It’s a minimal Windows app, so the whole idea is to rely on Windows DLLs as much as possible.
actionfromafar 1 days ago [-]
Officially, one should not use KERNEL32.dll for instance but go via crt. In practice, most interfaces are stable.
delta_p_delta_x 1 days ago [-]
KERNEL32.DLL (in spite of the name) provides user-mode system services for the Windows API. The CRT provides the C99 API. There are many entry points to the same thing on Windows; you can do any of `malloc`/`HeapAlloc`/`new`/`VirtualAlloc` to get a void* memory buffer. `malloc` is from the CRT; `HeapAlloc` is from KERNEL32.DLL, and `new` is from the C++ runtime.
Dwedit 6 hours ago [-]
Many many different ways to allocate memory. malloc, new, HeapAlloc, LocalAlloc, GlobalAlloc, CoTaskMemAlloc, etc. GlobalAlloc and LocalAlloc are pretty much obsolete. "malloc" sometimes redirects to HeapAlloc with the default process heap, but only sometimes, it depends entirely on which compiler and CRT is used.
It just causes one big headache that a DLL can't simply return a pointer and have the caller use "free", because malloc/free can be incompatible across modules.
This just led to the COM standard, featuring reference-counted objects that don't care what underlying way was used to allocate the memory. For the situations where you do need memory buffers, COM enforces the use of CoTaskMemAlloc/CoTaskMemFree.
neonz80 1 days ago [-]
kernel32 is an official API, you're probably thinking of ntdll. CRT is the C-runtime. Not everything is written in C.
actionfromafar 1 days ago [-]
Yes, you are right, must have been thinking of ntdll.
rfgplk 1 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.
chuckadams 1 days ago [-]
A .COM file is exactly that, a pure binary that just starts executing at the first byte. Mind you the loader for those has gotten a smidge bigger since its first version.
QuantumNomad_ 1 days ago [-]
It should be an exe file you can double click and execute.
WillAdams 1 days ago [-]
For more of the same (though I wish source was available) which actually does something useful, see the various small utilities at
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.
“Runs a Windows message loop
Has a title bar, minimize, maximize, and close buttons, which all work as expected
Has a system menu with the same
Paints the background and some text centered in the middle, equal to or larger than "Dave's Tiny App"”
That Linux program:
“Let’s take an incredibly simple program, one that does nothing but return a number back to the operating system”
You know? FOR ONE expression our current neuralese-spewing friends could standarize on - I'd not mind this one (and the ilk) becoming "load-bearing", again.-
PS. Honest take :)
abcd_f 1 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.
smokel 23 hours ago [-]
Somewhat more meaningful was "INT 19h" (CD 19), which also took 2 bytes and started the boot loader, bypassing the slow boot sequence of most systems.
And wouldn't a single instruction such as NOP or HLT be simply 1 byte?
abcd_f 11 hours ago [-]
Yeah, but the first one does nothing at all and the second does nothing for a bit :)
AdieuToLogic 21 hours ago [-]
>> The smallest meaningful program for MS-DOS was exactly 2 bytes ...
> Somewhat more meaningful was "INT 19h" (CD 19) ...
I seem to remember the smallest MS-DOS program to be CD 20h saved as a `.com`.
iamthejuan 7 hours ago [-]
When I hear assembly, two people always comes into my mind, Chris Sawyer and Steve Gibson.
ggerules 1 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 1 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.
Bluestein 1 days ago [-]
> 100H yeah and basically a memory dump
... the days! :)
p0w3n3d 1 days ago [-]
Looks too kinky for me. WinAPI + C - okay. But not this
hnea3ekp5i 1 days ago [-]
Appreciate you writing it up
drdexebtjl 1 days ago [-]
[flagged]
JoeDaDude 1 days ago [-]
What about his contributions to human civilization? ;)
He got a world record score on the Tempest arcade game [1], then developed an AI which beat his own record[2]. His biggest failure was, that after rebuilding TEMPEST from arcade machine ROMS, he added levels to the game but never made them public [3].
My how the overton window has moved. Some of violative conduct is standard practice now.
> When consumers prepared to purchase a product, additional services and products including a $9.95 back-up disc and $4.95 ‘optional extended service’ plan appeared on the check-out form. The form also listed “one free year of updates” – selected by default – but the company was then authorized to automatically charge a consumer’s credit card at the end of the year unless the buyer cancels the update plan.
drdexebtjl 1 days ago [-]
But also things that are absolutely not okay:
> Inducing computer users to install software by misrepresenting that the user's computer is at risk for crashes or privacy and security invasions.
> Marketing its InternetShield software by means of a “free scan.”
> Using “buttons” in its advertisements that do not function as the user would expect them. For example, the X found in the corner of a window is normally associated with closing the window and should not open another ad.
Installing software on a user’s computer that causes multiple pop-up advertisements when the user tries to close out of advertisements.
> Failing to provide a functional uninstall option for removing all software files.
> Failing to obtain a consumer’s explicit consent to purchase a product or a service.
skinfaxi 1 days ago [-]
Yes I thought I accounted for that with my use of "some". I wasn't intending to downplay anything.
Keyframe 1 days ago [-]
Dave Cutler was a guest in his garage and it was a great episode. That lands some gravity at least?
whobre 1 days ago [-]
Also Raymond Chen
silisili 1 days ago [-]
It's frustrating, because he does do some cool things. But I had to quit following him because of his constant yarning about how he grew up not rich and made millions from Microsoft, so young people now are stupid and lazy.
rvz 1 days ago [-]
Do you have any evidence of these (unsubstantiated) claims against him?
drdexebtjl 1 days ago [-]
Edited with previous threads linking court documents.
TiredOfLife 1 days ago [-]
He also lied about his contributions to Start menu
taf2 1 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...
eggy 1 days ago [-]
I haven't played with yolo yet. I'll have to use my airgapped, old Lenovo ThinkPad for this! Whenever I see yolo, I can't stop thinking of Joseph Redmon's YOLO and his astounding resume format!
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.
Windows 10 makes it literally impossible to write something that uses low memory and uses an actual window.
One trick I know of to make user32 a bit more lightweight is to call ImmDisableIme prior to creating your first window. This disables a lot of the TSF integration, which is notably quite slow. Not sure if it impacts memory footprint but worth a try. It of course does what the name says and disables IME support, so not a viable option if you have users who need IME
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.
Since the low-level Windows kernel API is undocumented and non-public, using these system DLLs is your only option on Windows.
It's just like linking against libc.so on any POSIX systems.
but also why would you, not much point except for very niche functionality
I mean officially. Yes, you can find some on the internet, but nothing on the official MSDN.
> but also why would you, not much point except for very niche functionality
Exactly. Using system DLL API is backward and forward compatible, and just as standardized and well-documented as the POSIX API. I see no problem relying on it.
(Sidenote: as a bonus, MSDN is surprisingly good, understandable, well organized, lots of examples. I rarely say this, but well done MS, that's how a dev doc should be.)
> I mean officially. Yes, you can find some on the internet, but nothing on the official MSDN.
It seems that changed. https://learn.microsoft.com/en-us/windows/win32/devnotes/ntq... says
but it on the official MSDN site, and it does document a call in Ntdll.dll.It’s easy to find many more examples such as https://learn.microsoft.com/en-us/windows/win32/api/winternl..., so I don’t think that’s an accident.
Does it? What's FILE_BASIC_INFORMATION? Link gives me 404. How do you replace kernel32 API with this?
> It’s easy to find many more examples such as https://learn.microsoft.com/en-us/windows/win32/api/winternl..., so I don’t think that’s an accident.
Again, how do you replace kernel32 API with this?
> In addition a bunch are documented in the driver docs, such as https://learn.microsoft.com/en-us/windows-hardware/drivers/d....
This has nothing to do with ntdll at all.
I still don't get it, what's wrong with using the user32 and kernel32 APIs? It's stable, well-documented, and is the official API on Windows. So why not use it?
> If the call to this function occurs in user mode, you should use the name "NtMapViewOfSection" instead of "ZwMapViewOfSection".
It just causes one big headache that a DLL can't simply return a pointer and have the caller use "free", because malloc/free can be incompatible across modules.
This just led to the COM standard, featuring reference-counted objects that don't care what underlying way was used to allocate the memory. For the situations where you do need memory buffers, COM enforces the use of CoTaskMemAlloc/CoTaskMemFree.
https://www.grc.com/freepopular.htm
A copy can be found at https://github.com/Dwedit/NoCopilotKey/blob/main/stub.bin
“Runs a Windows message loop Has a title bar, minimize, maximize, and close buttons, which all work as expected Has a system menu with the same Paints the background and some text centered in the middle, equal to or larger than "Dave's Tiny App"”
That Linux program:
“Let’s take an incredibly simple program, one that does nothing but return a number back to the operating system”
See https://archive.is/w01DO#selection-265.0-265.44 for a fairer comparison (97/133 bytes)
PS. Honest take :)
And wouldn't a single instruction such as NOP or HLT be simply 1 byte?
> Somewhat more meaningful was "INT 19h" (CD 19) ...
I seem to remember the smallest MS-DOS program to be CD 20h saved as a `.com`.
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
... the days! :)
He got a world record score on the Tempest arcade game [1], then developed an AI which beat his own record[2]. His biggest failure was, that after rebuilding TEMPEST from arcade machine ROMS, he added levels to the game but never made them public [3].
[1]. https://www.youtube.com/watch?v=EuSMCWu02hA
[2]. https://www.youtube.com/watch?v=TdbpoDjIvPk
[3]. https://www.youtube.com/watch?v=BjsVSEbXDOM
> When consumers prepared to purchase a product, additional services and products including a $9.95 back-up disc and $4.95 ‘optional extended service’ plan appeared on the check-out form. The form also listed “one free year of updates” – selected by default – but the company was then authorized to automatically charge a consumer’s credit card at the end of the year unless the buyer cancels the update plan.
> Inducing computer users to install software by misrepresenting that the user's computer is at risk for crashes or privacy and security invasions.
> Marketing its InternetShield software by means of a “free scan.”
> Using “buttons” in its advertisements that do not function as the user would expect them. For example, the X found in the corner of a window is normally associated with closing the window and should not open another ad. Installing software on a user’s computer that causes multiple pop-up advertisements when the user tries to close out of advertisements.
> Failing to provide a functional uninstall option for removing all software files.
> Failing to obtain a consumer’s explicit consent to purchase a product or a service.