Skip to content

Instantly share code, notes, and snippets.

@jdabtieu
Last active February 3, 2024 19:39
Show Gist options
  • Save jdabtieu/767af54a8e734639aa4428bd67ea08da to your computer and use it in GitHub Desktop.
Save jdabtieu/767af54a8e734639aa4428bd67ea08da to your computer and use it in GitHub Desktop.
64-bit Assembly Competitive Programming template with fast IO (minified version)
section .text
global _start
; int readint()
; byte _read_buf()
; void printint(int num) --> edi
; void newline()
; void printspace()
; void _write_buf(char *buf, int count) --> rdi, esi * max of BUF_SIZE characters (default 65536) at once
; void putchar(char c) --> dil
; void flush_obuf()
; rax caller-save function return value
; rbx callee-save
; rcx caller-save arg4
; rdx caller-save arg3
; rsi caller-save arg2
; rdi caller-save arg1
; r8 caller-save arg5
; r9 caller-save arg6
; r10 caller-save
; r11 caller-save
; r12 callee-save
; r13 callee-save
; r14 callee-save
; r15 callee-save
_start:
push rbp ; save base pointer
mov rbp, rsp ; place base pointer on stack
; change 16 bytes to however many bytes you need to allocate
sub rsp, 16
; your code here
end:
call flush_obuf ; flush output buffer very important
mov eax, 60 ; rax = 60 for sys_exit
xor edi, edi ; exit code = 0
syscall
readint:
push rbx
push rbp
mov rbp, rsp
sub rsp, 8
mov byte [rsp], 0
xor ebx, ebx
.discard_trash:
call _read_buf
cmp eax, 45
je .neg
sub eax, 48
cmp eax, 9
ja .discard_trash
.main:
lea ebx, [ebx+4*ebx]
add ebx, ebx
add ebx, eax
call _read_buf
sub eax, 48
cmp eax, 9
jbe .main
mov eax, ebx
neg ebx
cmp byte [rsp], 1
cmove eax, ebx
mov rsp, rbp
pop rbp
pop rbx
ret
.neg:
mov byte [rsp], 1
call _read_buf
sub eax, 48
jmp .main
printint:
push rbp
mov rbp, rsp
sub rsp, 20
cmp edi, 0
je _printint_zero
mov qword [rsp+8], 0
mov dword [rsp+16], 0
mov r8, rsp
add r8, 20
mov r11d, edi
sar r11d, 31
add edi, r11d
xor edi, r11d
jmp _printint_loop_cond
_printint_loop:
mov edx, edi
movsxd rax, edx
imul rax, rax, 1717986919
shr rax, 34
mov ecx, edx
shr ecx, 31
sub eax, ecx
mov edi, eax
shl eax, 2
add eax, edi
add eax, eax
sub edx, eax
add dl, 48
mov byte [r8], dl
dec r8
_printint_loop_cond:
cmp edi, 0
jne _printint_loop
_printint_done:
cmp r11, 0
je _printint_pos
mov byte [r8], 45
dec r8
_printint_pos:
lea rsi, [rsp+20]
lea rdi, [r8+1]
sub rsi, r8
call _write_buf
mov rsp, rbp
pop rbp
ret
_printint_zero:
mov edi, 48
call putchar
mov rsp, rbp
pop rbp
ret
newline:
mov edi, 10
jmp putchar
printspace:
mov edi, 32
jmp putchar
_read_buf:
mov ecx, dword [rel ibuf_start]
mov eax, dword [rel ibuf_end]
cmp ecx, eax
jge .extra
.main:
lea rdx, [rel input_buf]
add rdx, rcx
movzx eax, byte [rdx]
add dword [rel ibuf_start], 1
ret
.extra:
xor eax, eax
xor edi, edi
lea rsi, [rel input_buf]
mov rdx, 65536
syscall
mov dword [rel ibuf_start], 0
mov dword [rel ibuf_end], eax
xor ecx, ecx
jmp .main
_write_buf:
mov eax, dword [rel obuf_start]
add eax, esi
cmp eax, 65536
jge .extra
.main:
lea rcx, [rel output_buf]
mov eax, dword [rel obuf_start]
add rcx, rax
add dword [rel obuf_start], esi
.loop:
movzx edx, byte [rdi]
mov byte [rcx], dl
dec esi
inc rdi
inc rcx
test esi, esi
jnz .loop
ret
.extra:
push rdi
push rsi
call flush_obuf
pop rsi
pop rdi
jmp .main
putchar:
cmp dword [rel obuf_start], 65536
jl .main
push rdi
call flush_obuf
pop rdi
.main:
lea rax, [rel output_buf]
mov ecx, dword [rel obuf_start]
add rax, rcx
mov byte [rax], dil
add dword [rel obuf_start], 1
ret
flush_obuf:
mov eax, 1
mov edi, 1
lea rsi, [rel output_buf]
mov edx, dword [rel obuf_start]
syscall
mov dword [rel obuf_start], 0
ret
section .bss
input_buf: resb 65536
output_buf: resb 65536
section .data
ibuf_start: dd 65536
ibuf_end: dd 65536
obuf_start: dd 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment