<commit_before>.data
 missing_args: .ascii "Missing arguments!\n"
 missing_args_len: .quad . - missing_args

.section,bss
 .lcomm program, 50000 # Program
 .lcomm buffer, 30000 # Memory buffer

.text
.globl _main

##
# Interpreter implementation:
#     %rbx: program ptr
#     %rsi: data ptr (handy for sys_read and sys_write)
#     XXX missing regs
# 
# The program memory is statically allocated in the BSS section. The BSS 
# section is zero-filled at program start, so there's no need to clean it.
# The program itself is read from a file, obtained via command-line arguments,
# and also stored in a pre-allocated buffer in the BSS section.
#
# Considerations:
#  * Syscall numbers taken from /usr/include/sys/syscall.h
#  * Constants taken from /usr/include/sys/fcntl.h
#  * When invoking syscalls, the kernel destroys registers rcx and r11.
#  * x86_64 calling convention: sequence %rdi, %rsi, %rdx, %rcx, %r8 and %r9
##

_main:

##
# Obtain filename from stack and open it:
##
    # Check arguments count first:
    movq (%rsp), %rcx                   # "argc"
    cmp $0x02, %rcx
    jge get_filename
    # ssize_t write(int fildes, const void *buf, size_t nbyte);
    #               rdi         rsi              rdx
    movq $0x1, %rdi
    mov missing_args@GOTPCREL(%rip), %rsi
    mov missing_args_len@GOTPCREL(%rip), %rdx
    mov (%rdx), %rdx
    movq $0x2000004, %rax
    syscall
    jmp exit 

 get_filename:
    # int open(const char* path, int oflag, ...);
    #          rdi               rsi        rdx
    movq 16(%rsp), %rdi                 # XXX Stack layout
    xor %rsi, %rsi                      # O_RDONLY (0)
    movq $0x2000005, %rax               # SYS_open (5)
    syscall
    # XXX handle error (rax < 0)

 read_program:
##
# Read file contents in program buffer:
##

    # ssize_t read(int fildes, void *buf, size_t nbyte);
    #              rdi         rsi        rdx
    mov %rax, %rdi                      # fd (ret from open())
    mov program@GOTPCREL(%rip), %rsi    # Buffer to read into
    movq $50000, %rdx                   # Bufsize
    movq $0x2000003, %rax               # SYS_read (3)
    syscall
    # XXX handle error (rax < 0)

##
# Initialize interpreter:
##

    mov %rax, %r12                      # Store program length in %r12

    # XXX Store base address + length to speed up end-of-program check
    mov program@GOTPCREL(%rip), %rbx    # Initialize program ptr
    mov buffer@GOTPCREL(%rip), %rsi     # Initialize data ptr

##
# Main interpreter loop:
##

interpreter_loop:
    # Check if we reached program end: 
    movq program@GOTPCREL(%rip), %r8    # Load addr of program base
    addq %r12, %r8
    cmp %r8, %rbx<commit_msg>Using macros and improving end of program check<commit_after>.data
 missing_args: .ascii "Missing arguments!\n"
 missing_args_len: .quad . - missing_args
 
 usage: .ascii "Usage:\n\t./brainfuck <program name>\n"
 usage_len: .quad . - usage

 no_such_file: .ascii "No such file or directory"
 no_such_file_len: .quad . - no_such_file

.macro print_constant
 # ssize_t write(int fildes, const void *buf, size_t nbyte);
 #               rdi         rsi              rdx
 movq $$0x1, %rdi
 mov $0 @GOTPCREL(%rip), %rsi
 mov $0_len @GOTPCREL(%rip), %rdx
 mov (%rdx), %rdx
 movq $$0x2000004, %rax
 syscall
.endm

.section,bss
 .lcomm program, 50000 # Program
 .lcomm buffer, 30000 # Memory buffer

.text
.globl _main

##
# Interpreter implementation:
#     %rbx: program ptr
#     %rsi: data ptr (handy for sys_read and sys_write)
#     XXX missing regs
# 
# The program memory is statically allocated in the BSS section. The BSS 
# section is zero-filled at program start, so there's no need to clean it.
# The program itself is read from a file, obtained via command-line arguments,
# and also stored in a pre-allocated buffer in the BSS section.
#
# Considerations:
#  * Syscall numbers taken from /usr/include/sys/syscall.h
#  * Constants taken from /usr/include/sys/fcntl.h
#  * When invoking syscalls, the kernel destroys registers rcx and r11.
#  * x86_64 calling convention: sequence %rdi, %rsi, %rdx, %rcx, %r8 and %r9
##

_main:

##
# Obtain filename from stack and open it:
##
    # Check arguments count first:
    movq (%rsp), %rcx                   # "argc"
    cmp $0x02, %rcx
    jge get_filename
    print_constant missing_args
    print_constant usage
    jmp exit 

 get_filename:
    # int open(const char* path, int oflag, ...);
    #          rdi               rsi        rdx
    movq 16(%rsp), %rdi                 # XXX Stack layout
    xor %rsi, %rsi                      # O_RDONLY (0)
    movq $0x2000005, %rax               # SYS_open (5)
    syscall
    cmp $0x00, %rax # XXX 0x02 on error?
    jg read_program
    print_constant no_such_file
    jmp exit

##
# Read file contents in program buffer:
##

 read_program:
    # ssize_t read(int fildes, void *buf, size_t nbyte);
    #              rdi         rsi        rdx
    mov %rax, %rdi                      # fd (ret from open())
    mov program@GOTPCREL(%rip), %rsi    # Buffer to read into
    movq $50000, %rdx                   # Bufsize
    movq $0x2000003, %rax               # SYS_read (3)
    syscall
    # XXX handle error (rax < 0)

##
# Initialize interpreter:
##

    mov program@GOTPCREL(%rip), %rbx    # Initialize program ptr
    mov buffer@GOTPCREL(%rip), %rsi     # Initialize data ptr

    # Point %r12 to the end of the program:
    mov %rbx, %r12
    add %rax, %r12

##
# Main interpreter loop:
##

interpreter_loop:
    # Check if we reached program end: 
    cmp %r12, %rbx
{'fraction_non_alphanumeric': 0.10017985611510791, 'fraction_numerical': 0.02553956834532374, 'mean_word_length': 2.3239689181111776, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 4, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6370676', 'n_tokens_mistral': 2003, 'n_tokens_neox': 1852, 'n_words': 626}