From 2506ef66501378d50b0342a77ec91303029a7cfa Mon Sep 17 00:00:00 2001 From: Wes Hampson Date: Thu, 13 Jun 2019 03:04:43 -0700 Subject: [PATCH 01/18] Start on assembler --- CMakeLists.txt | 4 ++ include/as/lc3as.h | 6 +++ include/lc3tools.h | 2 + src/as/main.c | 123 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 135 insertions(+) create mode 100644 include/as/lc3as.h create mode 100644 src/as/main.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 54c3be4..7b260ff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,7 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) # Source files file(GLOB LIB_SOURCES "src/lib/*.c") +file(GLOB AS_SOURCES "src/as/*.c") file(GLOB EMU_SOURCES "src/emu/*.c") # Library for shared code @@ -13,8 +14,11 @@ add_library(lc3tools ${LIB_SOURCES}) target_include_directories(lc3tools PUBLIC include) # Executables +add_executable(lc3as ${AS_SOURCES}) add_executable(lc3emu ${EMU_SOURCES}) +target_include_directories(lc3as PRIVATE include/as) target_include_directories(lc3emu PRIVATE include/emu) # Link shared code and executables +target_link_libraries(lc3as lc3tools) target_link_libraries(lc3emu lc3tools) diff --git a/include/as/lc3as.h b/include/as/lc3as.h new file mode 100644 index 0000000..38d0e26 --- /dev/null +++ b/include/as/lc3as.h @@ -0,0 +1,6 @@ +#ifndef __LC3AS_H +#define __LC3AS_H + +#define LC3AS_TEST 6969 + +#endif /* __LC3AS_H */ diff --git a/include/lc3tools.h b/include/lc3tools.h index 69c8cd2..09e068d 100644 --- a/include/lc3tools.h +++ b/include/lc3tools.h @@ -28,6 +28,8 @@ */ #define DEBUG 1 +#define TEST_DIR "../test" + /* * File separator character. */ diff --git a/src/as/main.c b/src/as/main.c new file mode 100644 index 0000000..bf119b5 --- /dev/null +++ b/src/as/main.c @@ -0,0 +1,123 @@ +#include +#include +#include +#include + +#include +#include + +#define LINE_BUFFER_SIZE 256 + +struct source_file +{ + FILE *file; + char line[LINE_BUFFER_SIZE]; + size_t line_len; + size_t line_num; + size_t line_pos; +}; + +int read_line(struct source_file *src) +{ + src->line_num++; + if (feof(src->file) || fgets(src->line, LINE_BUFFER_SIZE, src->file) == 0) + { + return -1; + } + + src->line_len = strlen(src->line); + src->line_pos = 0; + + return src->line_len; +} + +int read_token(struct source_file *src, char **tok, char delim) +{ + size_t i; + // char *tok; + char *tok_head; + char *tok_tail; + char c; + int char_seen; + + if (src->line_pos >= src->line_len) + { + return 0; + } + + tok_head = &src->line[src->line_pos]; + tok_tail = tok_head; + i = 0; + char_seen = 0; + + while ((c = tok_head[i]) != '\0') + { + src->line_pos++; + if (isspace(c)) + { + if (!char_seen) + { + tok_head++; + tok_tail++; + continue; + } + else if (c == '\n') + { + *tok_tail = '\0'; + *tok = tok_head; + return 1; + } + else if (!isspace(delim)) + { + i++; + continue; + } + } + + char_seen = 1; + if (c == delim) + { + *tok_tail = '\0'; + *tok = tok_head; + return 1; + } + i++; + tok_tail++; + } + + return 0; +} + +int main(int argc, char *argv[]) +{ + struct source_file src; + char *tok; + + memset(&src, 0, sizeof(struct source_file)); + src.file = fopen(TEST_DIR"/astest2.asm", "rb"); + if (src.file == NULL) + { + return 2; + } + + while (read_line(&src) != -1) + { + read_token(&src, &tok, ' '); + // read_token(&src, &tok, '\t'); + + printf("tok: %s\n", tok); + if (strcasecmp(tok, "ADD") == 0) + { + printf("ADD\n"); + while ((read_token(&src, &tok, ',')) != 0) + { + printf("'%s'\n", tok); + } + } + } + + printf("Hit end of file! (line %zu)\n", src.line_num); + fclose(src.file); + + return 0; +} \ No newline at end of file From a741b2c44397549e499cc750b1196c5c4a2689b2 Mon Sep 17 00:00:00 2001 From: Wes Hampson Date: Thu, 13 Jun 2019 21:39:31 -0700 Subject: [PATCH 02/18] Second attempt at writing a parser... it still doesn't work But it's not done yet ;) --- src/as/main.c | 191 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 134 insertions(+), 57 deletions(-) diff --git a/src/as/main.c b/src/as/main.c index bf119b5..f8ed943 100644 --- a/src/as/main.c +++ b/src/as/main.c @@ -31,67 +31,48 @@ int read_line(struct source_file *src) return src->line_len; } -int read_token(struct source_file *src, char **tok, char delim) +int get_opcode(char *mnemonic, int *opcode, int *operand_count) { - size_t i; - // char *tok; - char *tok_head; - char *tok_tail; - char c; - int char_seen; - - if (src->line_pos >= src->line_len) + if (strcasecmp(mnemonic, "BR") == 0) { - return 0; + // TODO: nzp + *opcode = 0x0; + *operand_count = 1; + return 1; } - - tok_head = &src->line[src->line_pos]; - tok_tail = tok_head; - i = 0; - char_seen = 0; - - while ((c = tok_head[i]) != '\0') + else if (strcasecmp(mnemonic, "ADD") == 0) { - src->line_pos++; - if (isspace(c)) - { - if (!char_seen) - { - tok_head++; - tok_tail++; - continue; - } - else if (c == '\n') - { - *tok_tail = '\0'; - *tok = tok_head; - return 1; - } - else if (!isspace(delim)) - { - i++; - continue; - } - } - - char_seen = 1; - if (c == delim) - { - *tok_tail = '\0'; - *tok = tok_head; - return 1; - } - i++; - tok_tail++; + *opcode = 0x1; + *operand_count = 3; + return 1; + } + else if (strcasecmp(mnemonic, "RTI") == 0) + { + *opcode = 0x8; + *operand_count = 0; + return 1; } + *operand_count = 0; return 0; } int main(int argc, char *argv[]) { struct source_file src; - char *tok; + char *tok_head; + char *tok_tail; + char *mnemonic; + char *label; + char *operands[3]; + int opcode; + int operand_count; + int operand_idx; + int label_seen; + int mnemonic_seen; + int non_whitespace_seen; + int comment_seen; + int valid_mnemonic; memset(&src, 0, sizeof(struct source_file)); src.file = fopen(TEST_DIR"/astest2.asm", "rb"); @@ -102,17 +83,113 @@ int main(int argc, char *argv[]) while (read_line(&src) != -1) { - read_token(&src, &tok, ' '); - // read_token(&src, &tok, '\t'); + printf(">> line %zu...\n", src.line_num); - printf("tok: %s\n", tok); - if (strcasecmp(tok, "ADD") == 0) + operand_count = 0; + operand_idx = 0; + label_seen = 0; + mnemonic_seen = 0; + non_whitespace_seen = 0; + comment_seen = 0; + valid_mnemonic = 0; + + tok_head = src.line; + tok_tail = tok_head; + + while (src.line_pos <= src.line_len) { - printf("ADD\n"); - while ((read_token(&src, &tok, ',')) != 0) + switch (*tok_tail) { - printf("'%s'\n", tok); + case '\r': + { + goto next_char; + } + + case ',': + { + *tok_tail = '\0'; + operands[operand_idx++] = tok_head; + tok_head = tok_tail + 1; + goto next_char; + } + + case '\0': + case '\n': + case '\t': + case ' ': + { + if (comment_seen) + { + goto next_char; + } + if (!non_whitespace_seen) + { + tok_head++; + goto next_char; + } + + non_whitespace_seen = 0; + *tok_tail = '\0'; + if (!mnemonic_seen) + { + // Mnemonic + if (get_opcode(tok_head, &opcode, &operand_count)) + { + mnemonic_seen = 1; + mnemonic = tok_head; + } + } + if (!comment_seen && mnemonic_seen && operand_idx == operand_count - 1) + { + // Operand + operands[operand_idx++] = tok_head; + } + if (!mnemonic_seen && !label_seen) + { + // Label + label_seen = 1; + label = tok_head; + } + tok_head = tok_tail + 1; + goto next_char; + } + + case ';': + { + comment_seen = 1; + goto next_char; + } + + default: + { + if (comment_seen) + { + goto next_char; + } + + // TODO: restrict allowed characters + non_whitespace_seen = 1; + goto next_char; + } } + + next_char: + tok_tail++; + src.line_pos++; + } + + next_line: + if (label_seen) + { + printf("LABEL = '%s'\n", label); + } + if (mnemonic_seen) + { + printf("MNEMONIC = '%s'\n", mnemonic); + } + for (int i = 0; i < operand_count; i++) + { + printf("OPERAND%d = '%s'\n", i, operands[i]); } } @@ -120,4 +197,4 @@ int main(int argc, char *argv[]) fclose(src.file); return 0; -} \ No newline at end of file +} From 0a3f273d24ca622e686808d82eca37c697f7d7fe Mon Sep 17 00:00:00 2001 From: Wes Hampson Date: Fri, 14 Jun 2019 22:17:05 -0700 Subject: [PATCH 03/18] Third time's the charm (still WIP though) --- src/as/main.c | 333 +++++++++++++++++++++++++++----------------------- 1 file changed, 181 insertions(+), 152 deletions(-) diff --git a/src/as/main.c b/src/as/main.c index f8ed943..a622672 100644 --- a/src/as/main.c +++ b/src/as/main.c @@ -6,195 +6,224 @@ #include #include -#define LINE_BUFFER_SIZE 256 +#define LINE_BUFFER_SIZE 512 +#define TOKEN_BUFFER_SIZE 64 + +enum token_type +{ + T_LABEL, + T_MNEMONIC, + T_REGISTER, + T_IMMEDIATE +}; + +struct token +{ + struct token *next; + + int line; + int pos; + int len; + + enum token_type type; + char raw_str[TOKEN_BUFFER_SIZE]; + char cap_str[TOKEN_BUFFER_SIZE]; + int val; +}; struct source_file { FILE *file; char line[LINE_BUFFER_SIZE]; - size_t line_len; - size_t line_num; - size_t line_pos; + int line_num; + int line_pos; + int line_len; }; -int read_line(struct source_file *src) +static struct token * read_token(struct source_file *src); +static int read_line(struct source_file *src); + +int main(int argc, char *argv[]) { - src->line_num++; - if (feof(src->file) || fgets(src->line, LINE_BUFFER_SIZE, src->file) == 0) + struct source_file src; + + struct token *tok_list; + struct token *prev; + struct token *curr; + + if (argc < 2) { - return -1; + fprintf(stderr, "error: missing source file\n"); + return 1; } - src->line_len = strlen(src->line); - src->line_pos = 0; + memset(&src, 0, sizeof(struct source_file)); + src.file = fopen(argv[1], "rb"); + if (src.file == NULL) + { + fprintf(stderr, "error: failed to open source file\n"); + return 2; + } - return src->line_len; -} + if (read_line(&src) == -1) + { + fprintf(stderr, "error: failed to read source file\n"); + return 2; + } -int get_opcode(char *mnemonic, int *opcode, int *operand_count) -{ - if (strcasecmp(mnemonic, "BR") == 0) + prev = NULL; + while ((curr = read_token(&src)) != NULL) { - // TODO: nzp - *opcode = 0x0; - *operand_count = 1; - return 1; + printf("(%d:%d, %d): ", curr->line, curr->pos, curr->len); + switch (curr->type) + { + case T_LABEL: + printf("