Split my fasm code into reusable chunks
This commit is contained in:
parent
b7daaa989f
commit
7cef5d2316
@ -1,127 +1,6 @@
|
||||
format ELF64 executable 3
|
||||
|
||||
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 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
|
||||
}
|
||||
include "lib/linux_syscall.inc"
|
||||
include "lib/itoa.inc"
|
||||
|
||||
segment readable executable
|
||||
entry main
|
||||
@ -154,14 +33,20 @@ lp:
|
||||
cmp byte [rbx], '('
|
||||
;; If so, jump to "up"
|
||||
je up
|
||||
;; If not, it's the "go down" character, so decrement the current floor
|
||||
dec rcx
|
||||
;; Skip over the "increment"
|
||||
jmp moved
|
||||
;; Is the current character the "go down" character?
|
||||
cmp byte [rbx], ')'
|
||||
;; If so, it's the "go down" character, so decrement the current floor
|
||||
je down
|
||||
;; Otherwise it's the EOF probably, skip it
|
||||
jmp other
|
||||
up:
|
||||
;; We should "go up", so increment the current floor
|
||||
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
|
||||
inc rbx
|
||||
;; Count down the file's length
|
||||
@ -217,52 +102,6 @@ done:
|
||||
;; Done!
|
||||
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
|
||||
input_filename db '../data/2015/1/input.txt', 0
|
||||
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
|
||||
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