static long sys_write(int fd, const char *buf, long len) { long ret; __asm__ volatile ( "syscall" : "=a"(ret) : "0"(1L), "D"((long)fd), "S"(buf), "d"(len) : "rcx", "r11", "memory" ); return ret; } static void sys_exit(int code) { __asm__ volatile ( "syscall" : : "a"(60L), "D"((long)code) : ); __builtin_unreachable(); } static long strlen(const char *s) { long n = 0; while (s[n]) n++; return n; } static void print_char(char c) { sys_write(1, &c, 1); } static void str(const char *s) { long n = strlen(s); if (n > 0) sys_write(1, s, n); } static void uint(unsigned long v) { char buf[20]; int i = 19; buf[i] = '\0'; if (v == 0) { print_char('0'); return; } while (v && i > 0) { buf[--i] = '0' + (v % 10); v /= 10; } str(buf + i); } static void print_int(long v) { if (v < 0) { print_char('-'); uint((unsigned long)-v); } else uint((unsigned long)v); } static void hex(unsigned long v) { static const char *digits = "0123456789abcdef"; char buf[17]; int i = 16; buf[i] = '\0'; if (v == 0) { str("0x0"); return; } while (v && i > 0) { buf[--i] = digits[v & 0xf]; v >>= 4; } buf[--i] = 'x'; buf[--i] = '0'; str(buf + i); } typedef __builtin_va_list va_list; #define va_start(ap, last) __builtin_va_start(ap, last) #define va_arg(ap, T) __builtin_va_arg(ap, T) #define va_end(ap) __builtin_va_end(ap) static void impl(const char *fmt, ...) { va_list ap; va_start(ap, fmt); for (const char *p = fmt; *p; p++) { if (*p != '%') { print_char(*p); continue; } p++; switch (*p) { case 'd': print_int(va_arg(ap, int)); break; case 'l': p++; /* assume %ld */ print_int(va_arg(ap, long)); break; case 'u': uint(va_arg(ap, unsigned int)); break; case 'x': hex(va_arg(ap, unsigned long)); break; case 's': str(va_arg(ap, const char *)); break; case 'c': print_char((char)va_arg(ap, int)); break; case '%': print_char('%'); break; default: print_char('%'); print_char(*p); break; } } va_end(ap); } #define print(fmt, ...) impl((fmt), ##__VA_ARGS__) void _start(void) { print("Hello, world!\n"); print("Integer: %d\n", -42); print("Unsigned: %u\n", 1337u); print("Hex: %x\n", (unsigned long)0xDEADBEEF); print("String: %s\n", "no libc needed"); print("Char: %c\n", 'Z'); print("Long: %ld\n", (long)-9876543210L); print("Two args: %d + %d = %d\n", 10, 20, 30); sys_exit(0); }