Last active
March 17, 2026 13:57
-
-
Save skeeto/618eadfd970717103f243ecbbb920f35 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // $ cc -nostartfiles -o hello.exe hello.c | |
| // $ ./hello world | |
| // Ref: https://github.com/skeeto/w64devkit/discussions/340 | |
| // This is free and unencumbered software released into the public domain. | |
| #include <stdint.h> | |
| #include <uchar.h> | |
| #define nil ((uintptr_t)0) | |
| typedef uintptr_t Syscall(...); | |
| typedef struct { | |
| Syscall *ExitProcess; | |
| Syscall *GetCommandLineW; | |
| Syscall *GetProcAddress; | |
| Syscall *GetStdHandle; | |
| Syscall *LoadLibraryA; | |
| Syscall *WriteConsoleW; | |
| } Kernel32; | |
| typedef struct { | |
| Syscall *CommandLineToArgvW; | |
| } Shell32; | |
| static Kernel32 new_kernel32() | |
| { | |
| Syscall LoadLibraryA, GetProcAddress; // bootstrap | |
| uintptr_t h = LoadLibraryA("kernel32"); | |
| return (Kernel32){ | |
| .ExitProcess = (Syscall *)GetProcAddress(h, "ExitProcess"), | |
| .GetCommandLineW = (Syscall *)GetProcAddress(h, "GetCommandLineW"), | |
| .GetProcAddress = (Syscall *)GetProcAddress(h, "GetProcAddress"), | |
| .GetStdHandle = (Syscall *)GetProcAddress(h, "GetStdHandle"), | |
| .LoadLibraryA = (Syscall *)GetProcAddress(h, "LoadLibraryA"), | |
| .WriteConsoleW = (Syscall *)GetProcAddress(h, "WriteConsoleW"), | |
| }; | |
| } | |
| static Shell32 new_shell32(Kernel32 kernel32) | |
| { | |
| uintptr_t h = kernel32.LoadLibraryA("shell32"); | |
| return (Shell32){ | |
| .CommandLineToArgvW = | |
| (Syscall *)kernel32.GetProcAddress(h, "CommandLineToArgvW"), | |
| }; | |
| } | |
| static ptrdiff_t char16len(char16_t *s) | |
| { | |
| ptrdiff_t len = 0; | |
| for (; s[len]; len++) {} | |
| return len; | |
| } | |
| void mainCRTStartup() | |
| { | |
| Kernel32 kernel32 = new_kernel32(); | |
| Shell32 shell32 = new_shell32(kernel32); | |
| char16_t *cmd = (char16_t *)kernel32.GetCommandLineW(); | |
| int argc = {}; | |
| char16_t **argv = (char16_t **)shell32.CommandLineToArgvW(cmd, &argc); | |
| uintptr_t out = kernel32.GetStdHandle(-11); | |
| for (int i = 1; i < argc; i++) { | |
| kernel32.WriteConsoleW(out, u"hello, ", 7, nil, nil); | |
| kernel32.WriteConsoleW(out, argv[i], char16len(argv[i]), nil, nil); | |
| kernel32.WriteConsoleW(out, u"\n", 1, nil, nil); | |
| } | |
| kernel32.ExitProcess(0); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment