diff options
| author | Charles Cabergs <me@cacharle.xyz> | 2021-11-17 17:56:09 +0100 |
|---|---|---|
| committer | Charles Cabergs <me@cacharle.xyz> | 2021-11-17 18:02:27 +0100 |
| commit | 390f6c5360fdc8f49c1ecbd1747a0fb5f5282225 (patch) | |
| tree | d93bd4b8acfa0ce95467cbd2462b2f8a6a389894 | |
| parent | 285b331ac60d075bba4f721fe412a52576f50539 (diff) | |
| download | bfc-390f6c5360fdc8f49c1ecbd1747a0fb5f5282225.tar.gz bfc-390f6c5360fdc8f49c1ecbd1747a0fb5f5282225.tar.bz2 bfc-390f6c5360fdc8f49c1ecbd1747a0fb5f5282225.zip | |
Added Makefile
| -rw-r--r-- | .gitignore | 4 | ||||
| -rw-r--r-- | Makefile | 53 | ||||
| -rw-r--r-- | bfc.c | 54 | ||||
| -rw-r--r-- | examples/hello_world.bf | 43 | ||||
| -rw-r--r-- | examples/rot13.bf | 28 |
5 files changed, 163 insertions, 19 deletions
@@ -1,3 +1,5 @@ *.o a.out -*.asm +bin/* +asm/* +bfc diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..b405f94 --- /dev/null +++ b/Makefile @@ -0,0 +1,53 @@ +CC = gcc +CCFLAGS = -Wall -Wextra +NASM = nasm + +ifeq ($(shell uname),Linux) + NASMFLAGS = -f elf64 +endif +ifeq ($(shell uname),Darwin) + NASMFLAGS = -f macho64 +endif +ifeq ($(NASMFLAGS),) + $(error architecture: $(shell uname) not recognized) +endif + +SRC = bfc.c +NAME = bfc + +ASMDIR = asm +BINDIR = bin + +EXAMPLESDIR = examples +EXAMPLES = $(shell find $(EXAMPLESDIR) -name '*.bf' -type f) +EXAMPLES_ASM = $(EXAMPLES:$(EXAMPLESDIR)/%.bf=$(ASMDIR)/%.asm) +EXAMPLES_NAME = $(EXAMPLES:$(EXAMPLESDIR)/%.bf=$(BINDIR)/%) + +all: $(NAME) $(EXAMPLES_NAME) + +$(NAME): bfc.c + $(CC) $(CCFLAGS) -o $@ $< + +$(BINDIR)/%: $(ASMDIR)/%.asm $(BINDIR) + $(NASM) $(NASMFLAGS) -o $@.o $< + ld -o $@ $@.o + +$(ASMDIR)/%.asm: $(EXAMPLESDIR)/%.bf $(ASMDIR) + ./$(NAME) < $< > $@ + +$(BINDIR): + mkdir -pv $@ + +$(ASMDIR): + mkdir -pv $@ + +clean: + - rm -rv $(ASMDIR) + - rm -rv $(BINDIR) + - rm $(NAME) + +re: clean all + +# weird GNU make behavior where it rm's every asm files at the end +# (https://stackoverflow.com/questions/47447369) +.PRECIOUS: $(EXAMPLES_ASM) @@ -1,3 +1,4 @@ +#include <getopt.h> #include <stddef.h> #include <stdlib.h> #include <stdio.h> @@ -11,6 +12,23 @@ static size_t label_stack_frame = 0; int main(int argc, char *argv[]) { + int option; + + /* while ((option = getopt(argc, argv, "So:b:")) != -1) */ + /* { */ + /* switch (option) */ + /* { */ + /* case 'S': */ + /* assembly = true; */ + /* case 'o': */ + /* output_filename = optstring */ + /* case 'b': */ + /* buffer_length = atoi(optstring); */ + /* case 'e': */ + /* // byte, word, dword or qword */ + /* buffer_elem = x; */ + /* } */ + /* } */ FILE *input_file = NULL; if (argc == 2) input_file = fopen(argv[1], "r"); @@ -21,10 +39,10 @@ int main(int argc, char *argv[]) FILE *output_file = stdout; fprintf( output_file, + "global _start\n\n" "section .bss\n" "\tbuffer: resb %zu\n\n" "section .text\n" - "global _start\n" "_start:\n" "\tmov rbx, buffer\n", buffer_size @@ -37,35 +55,35 @@ int main(int argc, char *argv[]) switch (c) { case '>': - fprintf(output_file, " inc rbx ; >\n"); + fprintf(output_file, " inc rbx ; >\n"); break; case '<': - fprintf(output_file, " dec rbx ; <\n"); + fprintf(output_file, " dec rbx ; <\n"); break; case '+': - fprintf(output_file, " inc byte [rbx] ; +\n"); + fprintf(output_file, " inc byte [rbx] ; +\n"); break; case '-': - fprintf(output_file, " dec byte [rbx] ; -\n"); + fprintf(output_file, " dec byte [rbx] ; -\n"); break; case '.': - fprintf(output_file, " mov rdi, 1 ; .\n"); - fprintf(output_file, " mov rsi, rbx ; .\n"); - fprintf(output_file, " mov rdx, 1 ; .\n"); - fprintf(output_file, " mov rax, 1 ; .\n"); - fprintf(output_file, " syscall ; .\n"); + fprintf(output_file, " mov rdi, 1 ; .\n"); + fprintf(output_file, " mov rsi, rbx ; .\n"); + fprintf(output_file, " mov rdx, 1 ; .\n"); + fprintf(output_file, " mov rax, 1 ; .\n"); + fprintf(output_file, " syscall ; .\n"); break; case ',': - fprintf(output_file, " mov rdi, 0 ; ,\n"); - fprintf(output_file, " mov rsi, rbx ; ,\n"); - fprintf(output_file, " mov rdx, 1 ; ,\n"); - fprintf(output_file, " mov rax, 0 ; ,\n"); - fprintf(output_file, " syscall ; ,\n"); + fprintf(output_file, " mov rdi, 0 ; ,\n"); + fprintf(output_file, " mov rsi, rbx ; ,\n"); + fprintf(output_file, " mov rdx, 1 ; ,\n"); + fprintf(output_file, " mov rax, 0 ; ,\n"); + fprintf(output_file, " syscall ; ,\n"); break; case '[': label_frame_id = label_stack[label_stack_frame]; fprintf(output_file, "label_open_%03zu_%03zu: ; [\n", label_stack_frame, label_frame_id); - fprintf(output_file, " cmp byte [rbx], 0 ; [\n"); + fprintf(output_file, " cmp byte [rbx], 0 ; [\n"); fprintf(output_file, " je label_close_%03zu_%03zu ; [\n", label_stack_frame, label_frame_id); label_stack_frame++; break; @@ -73,7 +91,7 @@ int main(int argc, char *argv[]) label_stack_frame--; label_frame_id = label_stack[label_stack_frame]; fprintf(output_file, "label_close_%03zu_%03zu: ; ]\n", label_stack_frame, label_frame_id); - fprintf(output_file, " cmp byte [rbx], 0 ; ]\n"); + fprintf(output_file, " cmp byte [rbx], 0 ; ]\n"); fprintf(output_file, " jne label_open_%03zu_%03zu ; ]\n", label_stack_frame, label_frame_id); label_stack[label_stack_frame]++; break; @@ -85,10 +103,10 @@ int main(int argc, char *argv[]) // error } } + fprintf(output_file, "\n"); fprintf(output_file, " mov rdi, 0 ; exit\n"); fprintf(output_file, " mov rax, 60 ; exit\n"); fprintf(output_file, " syscall ; exit\n"); - return 0; } diff --git a/examples/hello_world.bf b/examples/hello_world.bf new file mode 100644 index 0000000..2a5b338 --- /dev/null +++ b/examples/hello_world.bf @@ -0,0 +1,43 @@ +[ ; This program prints "Hello World!" and a newline to the screen, its + ; length is 106 active command characters. [It is not the shortest.] + + ; This loop is an "initial comment loop", a simple way of adding a comment + ; to a BF program such that you don't have to worry about any command + ; characters. Any ".", ",", "+", "-", "<" and ">" characters are simply + ; ignored, the "[" and "]" characters just have to be balanced. This + ; loop and the commands it contains are ignored because the current cell + ; defaults to a value of 0; the 0 value causes this loop to be skipped. +] +++++++++ ; Set Cell #0 to 8 +[ + >++++ ; Add 4 to Cell #1; this will always set Cell #1 to 4 + [ ; as the cell will be cleared by the loop + >++ ; Add 2 to Cell #2 + >+++ ; Add 3 to Cell #3 + >+++ ; Add 3 to Cell #4 + >+ ; Add 1 to Cell #5 + <<<<- ; Decrement the loop counter in Cell #1 + ] ; Loop until Cell #1 is zero; number of iterations is 4 + >+ ; Add 1 to Cell #2 + >+ ; Add 1 to Cell #3 + >- ; Subtract 1 from Cell #4 + >>+ ; Add 1 to Cell #6 + [<] ; Move back to the first zero cell you find; this will + ; be Cell #1 which was cleared by the previous loop + <- ; Decrement the loop Counter in Cell #0 +] ; Loop until Cell #0 is zero; number of iterations is 8 + +; The result of this is: +; Cell no : 0 1 2 3 4 5 6 +; Contents: 0 0 72 104 88 32 8 +; Pointer : ^ + +>>. ; Cell #2 has value 72 which is 'H' +>---. ; Subtract 3 from Cell #3 to get 101 which is 'e' ++++++++..+++. ; Likewise for 'llo' from Cell #3 +>>. ; Cell #5 is 32 for the space +<-. ; Subtract 1 from Cell #4 for 87 to give a 'W' +<. ; Cell #3 was set to 'o' from the end of 'Hello' ++++.------.--------. ; Cell #3 for 'rl' and 'd' +>>+. ; Add 1 to Cell #5 gives us an exclamation point +>++. ; And finally a newline from Cell #6 diff --git a/examples/rot13.bf b/examples/rot13.bf new file mode 100644 index 0000000..3ce3faf --- /dev/null +++ b/examples/rot13.bf @@ -0,0 +1,28 @@ +-,+[ ; Read first character and start outer character reading loop + -[ ; Skip forward if character is 0 + >>++++[>++++++++<-] ; Set up divisor (32) for division loop + ; (MEMORY LAYOUT: dividend copy remainder divisor quotient zero zero) + <+<-[ ; Set up dividend (x minus 1) and enter division loop + >+>+>-[>>>] ; Increase copy and remainder / reduce divisor / Normal case: skip forward + <[[>+<-]>>+>] ; Special case: move remainder back to divisor and increase quotient + <<<<<- ; Decrement dividend + ] ; End division loop + ]>>>[-]+ ; End skip loop; zero former divisor and reuse space for a flag + >--[-[<->+++[-]]]<[ ; Zero that flag unless quotient was 2 or 3; zero quotient; check flag + ++++++++++++<[ ; If flag then set up divisor (13) for second division loop + ; (MEMORY LAYOUT: zero copy dividend divisor remainder quotient zero zero) + >-[>+>>] ; Reduce divisor; Normal case: increase remainder + >[+[<+>-]>+>>] ; Special case: increase remainder / move it back to divisor / increase quotient + <<<<<- ; Decrease dividend + ] ; End division loop + >>[<+>-] ; Add remainder back to divisor to get a useful 13 + >[ ; Skip forward if quotient was 0 + -[ ; Decrement quotient and skip forward if quotient was 1 + -<<[-]>> ; Zero quotient and divisor if quotient was 2 + ]<<[<<->>-]>> ; Zero divisor and subtract 13 from copy if quotient was 1 + ]<<[<<+>>-] ; Zero divisor and add 13 to copy if quotient was 0 + ] ; End outer skip loop (jump to here if ((character minus 1)/32) was not 2 or 3) + <[-] ; Clear remainder from first division if second division was skipped + <.[-] ; Output ROT13ed character from copy and clear it + <-,+ ; Read next character +] ; End character reading loop |
