Last active
June 5, 2025 21:52
-
-
Save skeeto/092ab3b3b2c9558111e4b0890fbaab39 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
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 |
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
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