Skip to content

Instantly share code, notes, and snippets.

@skeeto
Last active June 5, 2025 21:52
Show Gist options
  • Save skeeto/092ab3b3b2c9558111e4b0890fbaab39 to your computer and use it in GitHub Desktop.
Save skeeto/092ab3b3b2c9558111e4b0890fbaab39 to your computer and use it in GitHub Desktop.
global _start
_start:
mov rdi, rsp
xor r10d, r10d
lea r13, [rel nl]
push r12
push rbp
push rbx
mov rbx, rdi
sub rsp, 1040
mov r12d, dword [rdi]
and dword [rsp+1024+8], 0
.loop: cmp r12d, r10d
jle .done
mov rsi, qword [rbx+r10*8+8]
lea rbp, [rsp+8]
inc r10
mov rdi, rbp
call print
mov rsi, r13
mov rdi, rbp
call print
jmp .loop
.done: cmp dword [rsp+0x40c], 0
jnz .exit
movsxd rdx, dword [rsp+1024+8]
test edx, edx
jz .exit
push 1
pop rax
mov edi, eax
lea rsi, [rsp+8]
syscall
movsxd rdx, dword [rsp+1024+8]
cmp rdx, rax
setne al
movzx eax, al
mov dword [rsp+1024+12], eax
.exit: push 60
pop rax
mov edi, dword [rsp+1024+12]
syscall
print: mov r8, rdi
mov r9, rsi
.loop: cmp dword [r8+1024+4], 0
jnz .done
cmp byte [r9], 0
jz .done
cmp dword [r8+1024], 1024
jnz .flush
push 1
pop rax
mov edx, 1024
mov rsi, r8
mov edi, eax
syscall
movsxd rdx, dword [r8+1024]
cmp rdx, rax
setne al
and dword [r8+1024], 0
movzx eax, al
mov dword [r8+1024+4], eax
.flush: movsxd rax, dword [r8+1024]
inc r9
lea edx, [rax+1]
mov dword [r8+1024], edx
mov dl, byte [r9-1]
mov byte [r8+rax], dl
jmp .loop
.done: ret
nl: db `\n`, 0
static long write(int fd, void *p, long n)
{
long r;
asm volatile (
"syscall"
: "=a"(r)
: "a"(1), "D"(fd), "S"(p), "d"(n) : "memory", "rcx", "r11"
);
return r;
}
static void exit(int status)
{
asm volatile ("syscall" : : "a"(60), "D"(status));
__builtin_unreachable();
}
typedef struct {
char buf[1<<10];
int len;
int err;
} Buffer;
static void flush(Buffer *b)
{
if (!b->err && b->len) {
b->err = write(1, b->buf, b->len) != b->len;
}
b->len = 0;
}
static void print(Buffer *b, char *s)
{
for (long i = 0; !b->err && s[i]; i++) {
if (b->len == (int)sizeof(b->buf)) {
flush(b);
}
b->buf[b->len++] = s[i];
}
}
__attribute((used))
static void entrypoint(long *rsp)
{
int argc = rsp[0];
char **argv = (char **)(rsp + 1);
Buffer b;
b.len = 0;
for (int i = 0; i < argc; i++) {
print(&b, argv[i]);
print(&b, "\n");
}
flush(&b);
exit(b.err);
}
asm (
"_start: .global _start\n"
" mov %rsp, %rdi\n"
" call entrypoint\n"
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment