push
This commit is contained in:
commit
80f5fdc2a4
1 changed files with 121 additions and 0 deletions
121
print.c
Normal file
121
print.c
Normal file
|
|
@ -0,0 +1,121 @@
|
||||||
|
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);
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue