Split my fasm code into reusable chunks
This commit is contained in:
parent
b7daaa989f
commit
7cef5d2316
@ -1,127 +1,6 @@
|
|||||||
format ELF64 executable 3
|
format ELF64 executable 3
|
||||||
|
include "lib/linux_syscall.inc"
|
||||||
struc s_stat
|
include "lib/itoa.inc"
|
||||||
{
|
|
||||||
.st_dev dq 0
|
|
||||||
.st_ino dq 0
|
|
||||||
.st_nlink dq 0
|
|
||||||
.st_mode dd 0
|
|
||||||
.st_uid dd 0
|
|
||||||
.st_gid dq 0
|
|
||||||
.st_rdev dq 0
|
|
||||||
.st_size dq 0
|
|
||||||
.st_blksize dq 0
|
|
||||||
.st_blocks dq 0
|
|
||||||
.st_atim dq 0
|
|
||||||
.st_atim_nano dq 0
|
|
||||||
.st_mtim dq 0
|
|
||||||
.st_mtim_nano dq 0
|
|
||||||
.st_ctim dq 0
|
|
||||||
.st_ctim_nano dq 0
|
|
||||||
.st_atim_idk dq 0
|
|
||||||
.st_mtim_idk dq 0
|
|
||||||
.st_ctim_idk dq 0
|
|
||||||
}
|
|
||||||
|
|
||||||
macro syscall1 nr, arg1
|
|
||||||
{
|
|
||||||
mov rax, nr
|
|
||||||
mov rdi, arg1
|
|
||||||
syscall
|
|
||||||
}
|
|
||||||
|
|
||||||
macro syscall2 nr, arg1, arg2
|
|
||||||
{
|
|
||||||
mov rax, nr
|
|
||||||
mov rdi, arg1
|
|
||||||
mov rsi, arg2
|
|
||||||
syscall
|
|
||||||
}
|
|
||||||
|
|
||||||
macro syscall3 nr, arg1, arg2, arg3
|
|
||||||
{
|
|
||||||
mov rax, nr
|
|
||||||
mov rdi, arg1
|
|
||||||
mov rsi, arg2
|
|
||||||
mov rdx, arg3
|
|
||||||
syscall
|
|
||||||
}
|
|
||||||
|
|
||||||
macro syscall6 nr, arg1, arg2, arg3, arg4, arg5, arg6
|
|
||||||
{
|
|
||||||
mov rax, nr
|
|
||||||
mov rdi, arg1
|
|
||||||
mov rsi, arg2
|
|
||||||
mov rdx, arg3
|
|
||||||
mov r10, arg4
|
|
||||||
mov r8, arg5
|
|
||||||
mov r9, arg6
|
|
||||||
syscall
|
|
||||||
}
|
|
||||||
|
|
||||||
STDOUT equ 1
|
|
||||||
STDERR equ 2
|
|
||||||
|
|
||||||
SYS_read equ 0
|
|
||||||
;; ssize_t read(int fd, void buf[.count], size_t count);
|
|
||||||
macro read fd,buf,count
|
|
||||||
{
|
|
||||||
syscall3 SYS_read, fd, buf, count
|
|
||||||
}
|
|
||||||
|
|
||||||
SYS_write equ 1
|
|
||||||
;; ssize_t write(int fd, const void buf[.count], size_t count);
|
|
||||||
macro write fd,buf,count
|
|
||||||
{
|
|
||||||
syscall3 SYS_write, fd, buf, count
|
|
||||||
}
|
|
||||||
|
|
||||||
SYS_open equ 2
|
|
||||||
;; int open(const char *pathname, int flags);
|
|
||||||
macro open pathname, flags
|
|
||||||
{
|
|
||||||
syscall2 SYS_open, pathname, flags
|
|
||||||
}
|
|
||||||
|
|
||||||
SYS_close equ 3
|
|
||||||
;; int close(int fd);
|
|
||||||
macro close fd
|
|
||||||
{
|
|
||||||
syscall1 SYS_close, fd
|
|
||||||
}
|
|
||||||
|
|
||||||
SYS_stat equ 4
|
|
||||||
;; int stat(const char *restrict pathname
|
|
||||||
;; struct stat *restrict statbuf);
|
|
||||||
macro stat pathname, statbuf
|
|
||||||
{
|
|
||||||
syscall2 SYS_stat, pathname, statbuf
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PROT_READ equ 1
|
|
||||||
MAP_PRIVATE = 2
|
|
||||||
SYS_mmap equ 9
|
|
||||||
;; void *mmap(void addr[.length], size_t length, int prot, int flags,
|
|
||||||
;; int fd, off_t offset);
|
|
||||||
macro mmap addr, length, prot, flags, fd, offset
|
|
||||||
{
|
|
||||||
syscall6 SYS_mmap, addr, length, prot, flags, fd, offset
|
|
||||||
}
|
|
||||||
|
|
||||||
SYS_munmap equ 11
|
|
||||||
;; int munmap(void addr[.length], size_t length);
|
|
||||||
macro munmap addr, length
|
|
||||||
{
|
|
||||||
syscall2 SYS_munmap, addr, length
|
|
||||||
}
|
|
||||||
|
|
||||||
SYS_exit equ 60
|
|
||||||
;; [[noreturn]] void _exit(int status);
|
|
||||||
macro exit status
|
|
||||||
{
|
|
||||||
syscall1 SYS_exit, status
|
|
||||||
}
|
|
||||||
|
|
||||||
segment readable executable
|
segment readable executable
|
||||||
entry main
|
entry main
|
||||||
@ -154,14 +33,20 @@ lp:
|
|||||||
cmp byte [rbx], '('
|
cmp byte [rbx], '('
|
||||||
;; If so, jump to "up"
|
;; If so, jump to "up"
|
||||||
je up
|
je up
|
||||||
;; If not, it's the "go down" character, so decrement the current floor
|
;; Is the current character the "go down" character?
|
||||||
dec rcx
|
cmp byte [rbx], ')'
|
||||||
;; Skip over the "increment"
|
;; If so, it's the "go down" character, so decrement the current floor
|
||||||
jmp moved
|
je down
|
||||||
|
;; Otherwise it's the EOF probably, skip it
|
||||||
|
jmp other
|
||||||
up:
|
up:
|
||||||
;; We should "go up", so increment the current floor
|
;; We should "go up", so increment the current floor
|
||||||
inc rcx
|
inc rcx
|
||||||
moved:
|
jmp other
|
||||||
|
down:
|
||||||
|
;; We should "go down", so decrement the current floor
|
||||||
|
dec rcx
|
||||||
|
other:
|
||||||
;; Check the next character in the file
|
;; Check the next character in the file
|
||||||
inc rbx
|
inc rbx
|
||||||
;; Count down the file's length
|
;; Count down the file's length
|
||||||
@ -217,52 +102,6 @@ done:
|
|||||||
;; Done!
|
;; Done!
|
||||||
exit 0
|
exit 0
|
||||||
|
|
||||||
;; rax contains the integer
|
|
||||||
;; rbx contains a pointer to the string buffer
|
|
||||||
itoa:
|
|
||||||
mov byte [rbx], 48
|
|
||||||
mov byte [rbx + 1], 48
|
|
||||||
mov byte [rbx + 2], 48
|
|
||||||
mov byte [rbx + 3], 48
|
|
||||||
mov byte [rbx + 4], 48
|
|
||||||
mov byte [rbx + 5], 48
|
|
||||||
sub rax, 100000
|
|
||||||
inc byte [rbx]
|
|
||||||
cmp rax, 0
|
|
||||||
jge itoa
|
|
||||||
add rax, 100000
|
|
||||||
dec byte [rbx]
|
|
||||||
.ten_thousand:
|
|
||||||
sub rax, 10000
|
|
||||||
inc byte [rbx + 1]
|
|
||||||
cmp rax, 0
|
|
||||||
jge .ten_thousand
|
|
||||||
add rax, 10000
|
|
||||||
dec byte [rbx + 1]
|
|
||||||
.one_thousand:
|
|
||||||
sub rax, 1000
|
|
||||||
inc byte [rbx + 2]
|
|
||||||
cmp rax, 0
|
|
||||||
jge .one_thousand
|
|
||||||
add rax, 1000
|
|
||||||
dec byte [rbx + 2]
|
|
||||||
.one_hundred:
|
|
||||||
sub rax, 100
|
|
||||||
inc byte [rbx + 3]
|
|
||||||
cmp rax, 0
|
|
||||||
jge .one_hundred
|
|
||||||
add rax, 100
|
|
||||||
dec byte [rbx + 3]
|
|
||||||
.ten:
|
|
||||||
sub rax, 10
|
|
||||||
inc byte [rbx + 4]
|
|
||||||
cmp rax, 0
|
|
||||||
jge .ten
|
|
||||||
add rax, 10
|
|
||||||
dec byte [rbx + 4]
|
|
||||||
add [rbx + 5], rax
|
|
||||||
ret
|
|
||||||
|
|
||||||
segment readable writable
|
segment readable writable
|
||||||
input_filename db '../data/2015/1/input.txt', 0
|
input_filename db '../data/2015/1/input.txt', 0
|
||||||
input_fd dq -1
|
input_fd dq -1
|
||||||
|
22
fasm/2015/2/problem.asm
Normal file
22
fasm/2015/2/problem.asm
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
format ELF64 executable 3
|
||||||
|
include "lib/linux_syscall.inc"
|
||||||
|
include "lib/print.inc"
|
||||||
|
|
||||||
|
segment readable executable
|
||||||
|
entry main
|
||||||
|
|
||||||
|
main:
|
||||||
|
mov rdi, input_filename
|
||||||
|
call print_c_string
|
||||||
|
exit 0
|
||||||
|
|
||||||
|
segment readable writable
|
||||||
|
input_filename db '../data/2015/1/input.txt', 0, 'more text', 0
|
||||||
|
input_fd dq -1
|
||||||
|
input dq -1
|
||||||
|
part_1_verbiage db 'Part 1: ', 0
|
||||||
|
part_1 db ' ', 0
|
||||||
|
part_2_verbiage db 'Part 2: ', 0
|
||||||
|
part_2 db ' ', 0
|
||||||
|
newline db 10
|
||||||
|
file_stat s_stat
|
@ -3,4 +3,4 @@
|
|||||||
year=$1
|
year=$1
|
||||||
day=$2
|
day=$2
|
||||||
|
|
||||||
bin/fasm $year/$day/problem.asm $year/$day/problem && time ./$year/$day/problem
|
bin/fasm $year/$day/problem.asm $year/$day/problem && time ./$year/$day/problem
|
||||||
|
45
fasm/lib/itoa.inc
Normal file
45
fasm/lib/itoa.inc
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
;; rax contains the integer
|
||||||
|
;; rbx contains a pointer to the string buffer
|
||||||
|
itoa:
|
||||||
|
mov byte [rbx], '0'
|
||||||
|
mov byte [rbx + 1], '0'
|
||||||
|
mov byte [rbx + 2], '0'
|
||||||
|
mov byte [rbx + 3], '0'
|
||||||
|
mov byte [rbx + 4], '0'
|
||||||
|
mov byte [rbx + 5], '0'
|
||||||
|
sub rax, 100000
|
||||||
|
inc byte [rbx]
|
||||||
|
cmp rax, 0
|
||||||
|
jge itoa
|
||||||
|
add rax, 100000
|
||||||
|
dec byte [rbx]
|
||||||
|
.ten_thousand:
|
||||||
|
sub rax, 10000
|
||||||
|
inc byte [rbx + 1]
|
||||||
|
cmp rax, 0
|
||||||
|
jge .ten_thousand
|
||||||
|
add rax, 10000
|
||||||
|
dec byte [rbx + 1]
|
||||||
|
.one_thousand:
|
||||||
|
sub rax, 1000
|
||||||
|
inc byte [rbx + 2]
|
||||||
|
cmp rax, 0
|
||||||
|
jge .one_thousand
|
||||||
|
add rax, 1000
|
||||||
|
dec byte [rbx + 2]
|
||||||
|
.one_hundred:
|
||||||
|
sub rax, 100
|
||||||
|
inc byte [rbx + 3]
|
||||||
|
cmp rax, 0
|
||||||
|
jge .one_hundred
|
||||||
|
add rax, 100
|
||||||
|
dec byte [rbx + 3]
|
||||||
|
.ten:
|
||||||
|
sub rax, 10
|
||||||
|
inc byte [rbx + 4]
|
||||||
|
cmp rax, 0
|
||||||
|
jge .ten
|
||||||
|
add rax, 10
|
||||||
|
dec byte [rbx + 4]
|
||||||
|
add [rbx + 5], rax
|
||||||
|
ret
|
72
fasm/lib/linux_syscall.inc
Normal file
72
fasm/lib/linux_syscall.inc
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
include "macros.inc"
|
||||||
|
|
||||||
|
STDOUT equ 1
|
||||||
|
STDERR equ 2
|
||||||
|
|
||||||
|
SYS_read equ 0
|
||||||
|
;; ssize_t read(int fd, void buf[.count], size_t count);
|
||||||
|
macro read fd,buf,count
|
||||||
|
{
|
||||||
|
syscall3 SYS_read, fd, buf, count
|
||||||
|
}
|
||||||
|
|
||||||
|
SYS_write equ 1
|
||||||
|
;; ssize_t write(int fd, const void buf[.count], size_t count);
|
||||||
|
macro write fd,buf,count
|
||||||
|
{
|
||||||
|
syscall3 SYS_write, fd, buf, count
|
||||||
|
}
|
||||||
|
|
||||||
|
SYS_open equ 2
|
||||||
|
;; int open(const char *pathname, int flags);
|
||||||
|
macro open pathname, flags
|
||||||
|
{
|
||||||
|
syscall2 SYS_open, pathname, flags
|
||||||
|
}
|
||||||
|
|
||||||
|
SYS_close equ 3
|
||||||
|
;; int close(int fd);
|
||||||
|
macro close fd
|
||||||
|
{
|
||||||
|
syscall1 SYS_close, fd
|
||||||
|
}
|
||||||
|
|
||||||
|
SYS_stat equ 4
|
||||||
|
;; int stat(const char *restrict pathname
|
||||||
|
;; struct stat *restrict statbuf);
|
||||||
|
macro stat pathname, statbuf
|
||||||
|
{
|
||||||
|
syscall2 SYS_stat, pathname, statbuf
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PROT_READ equ 1
|
||||||
|
MAP_PRIVATE = 2
|
||||||
|
SYS_mmap equ 9
|
||||||
|
;; void *mmap(void addr[.length], size_t length, int prot, int flags,
|
||||||
|
;; int fd, off_t offset);
|
||||||
|
macro mmap addr, length, prot, flags, fd, offset
|
||||||
|
{
|
||||||
|
syscall6 SYS_mmap, addr, length, prot, flags, fd, offset
|
||||||
|
}
|
||||||
|
|
||||||
|
SYS_munmap equ 11
|
||||||
|
;; int munmap(void addr[.length], size_t length);
|
||||||
|
macro munmap addr, length
|
||||||
|
{
|
||||||
|
syscall2 SYS_munmap, addr, length
|
||||||
|
}
|
||||||
|
|
||||||
|
SYS_alarm equ 37
|
||||||
|
;; unsigned int alarm(unsigned int seconds);
|
||||||
|
macro alarm seconds
|
||||||
|
{
|
||||||
|
syscall1 SYS_alarm, seconds
|
||||||
|
}
|
||||||
|
|
||||||
|
SYS_exit equ 60
|
||||||
|
;; [[noreturn]] void _exit(int status);
|
||||||
|
macro exit status
|
||||||
|
{
|
||||||
|
syscall1 SYS_exit, status
|
||||||
|
}
|
79
fasm/lib/macros.inc
Normal file
79
fasm/lib/macros.inc
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
struc s_stat
|
||||||
|
{
|
||||||
|
.st_dev dq 0
|
||||||
|
.st_ino dq 0
|
||||||
|
.st_nlink dq 0
|
||||||
|
.st_mode dd 0
|
||||||
|
.st_uid dd 0
|
||||||
|
.st_gid dq 0
|
||||||
|
.st_rdev dq 0
|
||||||
|
.st_size dq 0
|
||||||
|
.st_blksize dq 0
|
||||||
|
.st_blocks dq 0
|
||||||
|
.st_atim dq 0
|
||||||
|
.st_atim_nano dq 0
|
||||||
|
.st_mtim dq 0
|
||||||
|
.st_mtim_nano dq 0
|
||||||
|
.st_ctim dq 0
|
||||||
|
.st_ctim_nano dq 0
|
||||||
|
.st_atim_idk dq 0
|
||||||
|
.st_mtim_idk dq 0
|
||||||
|
.st_ctim_idk dq 0
|
||||||
|
}
|
||||||
|
|
||||||
|
macro syscall1 nr, arg1
|
||||||
|
{
|
||||||
|
mov rax, nr
|
||||||
|
mov rdi, arg1
|
||||||
|
syscall
|
||||||
|
}
|
||||||
|
|
||||||
|
macro syscall2 nr, arg1, arg2
|
||||||
|
{
|
||||||
|
mov rax, nr
|
||||||
|
mov rdi, arg1
|
||||||
|
mov rsi, arg2
|
||||||
|
syscall
|
||||||
|
}
|
||||||
|
|
||||||
|
macro syscall3 nr, arg1, arg2, arg3
|
||||||
|
{
|
||||||
|
mov rax, nr
|
||||||
|
mov rdi, arg1
|
||||||
|
mov rsi, arg2
|
||||||
|
mov rdx, arg3
|
||||||
|
syscall
|
||||||
|
}
|
||||||
|
|
||||||
|
macro syscall4 nr, arg1, arg2, arg3, arg4
|
||||||
|
{
|
||||||
|
mov rax, nr
|
||||||
|
mov rdi, arg1
|
||||||
|
mov rsi, arg2
|
||||||
|
mov rdx, arg3
|
||||||
|
mov r10, arg4
|
||||||
|
syscall
|
||||||
|
}
|
||||||
|
|
||||||
|
macro syscall5 nr, arg1, arg2, arg3, arg4, arg5
|
||||||
|
{
|
||||||
|
mov rax, nr
|
||||||
|
mov rdi, arg1
|
||||||
|
mov rsi, arg2
|
||||||
|
mov rdx, arg3
|
||||||
|
mov r10, arg4
|
||||||
|
mov r8, arg5
|
||||||
|
syscall
|
||||||
|
}
|
||||||
|
|
||||||
|
macro syscall6 nr, arg1, arg2, arg3, arg4, arg5, arg6
|
||||||
|
{
|
||||||
|
mov rax, nr
|
||||||
|
mov rdi, arg1
|
||||||
|
mov rsi, arg2
|
||||||
|
mov rdx, arg3
|
||||||
|
mov r10, arg4
|
||||||
|
mov r8, arg5
|
||||||
|
mov r9, arg6
|
||||||
|
syscall
|
||||||
|
}
|
33
fasm/lib/print.inc
Normal file
33
fasm/lib/print.inc
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
include "linux_syscall.inc"
|
||||||
|
|
||||||
|
;; rdi contains the address of the null-terminated string to print to STDOUT
|
||||||
|
print_c_string:
|
||||||
|
;; initialize counter
|
||||||
|
mov rax, 0
|
||||||
|
|
||||||
|
;; initialize character pointer
|
||||||
|
mov rbx, rdi
|
||||||
|
|
||||||
|
.loop:
|
||||||
|
;; Is the current character \0?
|
||||||
|
cmp byte [rbx], 0
|
||||||
|
|
||||||
|
;; If so we can print
|
||||||
|
je .print
|
||||||
|
|
||||||
|
;; Otherwise, increment the counter and check the next character
|
||||||
|
inc rax
|
||||||
|
inc rbx
|
||||||
|
jmp .loop
|
||||||
|
|
||||||
|
.print:
|
||||||
|
;; rdi is the start point of the string to print
|
||||||
|
mov r11, rdi
|
||||||
|
|
||||||
|
;; rdx contains the number of characters to print
|
||||||
|
mov r12, rax
|
||||||
|
|
||||||
|
;; Write to STDOUT
|
||||||
|
write STDOUT, r11, r12
|
||||||
|
|
||||||
|
ret
|
Loading…
Reference in New Issue
Block a user