From 545bb8591e8003912b6c6b494acefd74e6b3abfd Mon Sep 17 00:00:00 2001 From: mrb0nk500 Date: Sat, 9 May 2020 14:14:08 -0400 Subject: Added support for single quote marks to the emulator's assembler. Single quote marks works in the assembler just like they do in C, except that it only supports a handful of escaped characters, like '\n', and '\r'. --- asmmon.c | 60 +++++++++++++++----- asmmon.h | 3 +- lexer.c | 154 ++++++++++++++++++++++++++------------------------- programs/subeditor.s | 65 +++++++++++----------- test/lex.s | 13 ++++- 5 files changed, 172 insertions(+), 123 deletions(-) diff --git a/asmmon.c b/asmmon.c index 453ff3c..198254c 100644 --- a/asmmon.c +++ b/asmmon.c @@ -114,6 +114,8 @@ void list(struct line *l, uint16_t start, uint16_t end, uint8_t all, uint8_t ln, uint8_t spaces; uint8_t tabs; char mne_lower[4]; + char ch[6]; + if (all) { end = lineidx; } @@ -202,10 +204,28 @@ void list(struct line *l, uint16_t start, uint16_t end, uint8_t all, uint8_t ln, } } + j = 0; + + if (l[i].opbase == BASE_CHAR) { + switch (l[i].op) { + default : ch[j++] = l[i].op; break; + case '\n': ch[j++] = '\\'; ch[j++] = 'n' ; break; + case '\r': ch[j++] = '\\'; ch[j++] = 'r' ; break; + case '\b': ch[j++] = '\\'; ch[j++] = 'b' ; break; + case '\\': ch[j++] = '\\'; ch[j++] = '\\'; break; + case '\'': ch[j++] = '\\'; ch[j++] = '\''; break; + case '\"': ch[j++] = '\\'; ch[j++] = '\"'; break; + } + } + + ch[j] = '\0'; + j = 0; + switch (l[i].opbase) { - case BASE_HEX: printf("$%"PRIX64, l[i].op); break; - case BASE_DEC: printf("%"PRIu64, l[i].op); break; - case BASE_BIN: printf("%%%s", showbits(l[i].op, bitnum, dbg)); break; + case BASE_HEX: printf("$%"PRIX64, l[i].op); break; + case BASE_DEC: printf("%"PRIu64, l[i].op); break; + case BASE_BIN: printf("%%%s", showbits(l[i].op, bitnum, dbg)); break; + case BASE_CHAR: printf("\'%s\'", ch); break; } bitnum = 0; opsize = 0; @@ -226,10 +246,29 @@ void list(struct line *l, uint16_t start, uint16_t end, uint8_t all, uint8_t ln, if (opsize) { bitnum = bitsize[opsize-1]; } + + j = 0; + + if (l[i].aopbase == BASE_CHAR) { + switch (l[i].aop) { + default : ch[j++] = l[i].aop; break; + case '\n': ch[j++] = '\\'; ch[j++] = 'n' ; break; + case '\r': ch[j++] = '\\'; ch[j++] = 'r' ; break; + case '\b': ch[j++] = '\\'; ch[j++] = 'b' ; break; + case '\\': ch[j++] = '\\'; ch[j++] = '\\'; break; + case '\'': ch[j++] = '\\'; ch[j++] = '\''; break; + case '\"': ch[j++] = '\\'; ch[j++] = '\"'; break; + } + } + + ch[j] = '\0'; + j = 0; + switch (l[i].aopbase) { - case BASE_HEX: printf("$%"PRIX64, l[i].aop); break; - case BASE_DEC: printf("%"PRIu64, l[i].aop); break; - case BASE_BIN: printf("%%%s", showbits(l[i].aop, bitnum, dbg)); break; + case BASE_HEX : printf("$%"PRIX64, l[i].aop); break; + case BASE_DEC : printf("%"PRIu64, l[i].aop); break; + case BASE_BIN : printf("%%%s", showbits(l[i].aop, bitnum, dbg)); break; + case BASE_CHAR: printf("\'%s\'", ch); break; } bitnum = 0; opsize = 0; @@ -443,14 +482,7 @@ uint64_t assemble(struct line *line, uint8_t dbg) { } tmpaddr += tmp; tmp = 0; - if (skip || flags & 0x80) { - if (dbg) { - printf("assemble(): The address that this line starts at is, $%"PRIX64".\n", address); - printf("assemble(): The address that this line ends on is, $%"PRIX64".\n", tmpaddr); - } - continue; - } - if (flags == 0x108) { + if (skip | (flags & 0x80) | (flags == 0x108)) { if (dbg) { printf("assemble(): The address that this line starts at is, $%"PRIX64".\n", address); printf("assemble(): The address that this line ends on is, $%"PRIX64".\n", tmpaddr); diff --git a/asmmon.h b/asmmon.h index 54b2ab7..58b4918 100644 --- a/asmmon.h +++ b/asmmon.h @@ -35,7 +35,8 @@ enum { enum { BASE_HEX, BASE_DEC, - BASE_BIN + BASE_BIN, + BASE_CHAR }; static const uint8_t opcodes[OPNUM][9] = { diff --git a/lexer.c b/lexer.c index 5a79325..6ed6cf4 100644 --- a/lexer.c +++ b/lexer.c @@ -153,14 +153,9 @@ uint16_t get_comment(const char *com, uint8_t dbg) { break; } } - if (comment[i] == NULL) { + if (comment[i] == NULL || i == comidx) { if (dbg) { printf("get_comment(): oof, the index $%04X is NULL.\n", i); - } - return 0xFFFF; - } - if (i == comidx) { - if (dbg) { printf("get_comment(): oof, the comment \"%s\", was not found in the comment table.\n", com); } return 0xFFFF; @@ -175,25 +170,17 @@ uint16_t get_string(const char *str, uint8_t dbg) { uint16_t i = 0; uint8_t isstr = 0; for (; i < stridx; i++) { - if (string[i] != NULL) { + if (isstr || string[i] == NULL) { + break; + } else { if (str[0] == string[i][0]) { isstr = !strcmp(str, string[i]); } - } else { - break; - } - if (isstr) { - break; } } - if (string[i] == NULL) { + if (string[i] == NULL || i == stridx) { if (dbg) { printf("get_string(): oof, the index $%04X is NULL.\n", i); - } - return 0xFFFF; - } - if (i == stridx) { - if (dbg) { printf("get_string(): oof, the string \"%s\", was not found in the string table.\n", str); } return 0xFFFF; @@ -405,12 +392,10 @@ uint64_t update_addr(struct line *ln, uint64_t address, uint8_t fixup, uint16_t uint16_t find_line(struct line *l, uint16_t ln, uint8_t dbg) { uint16_t i = 0; for (; i < lineidx && l[i].linenum != ln; i++); - if (l[i].linenum == ln) { - if (dbg) { + if (dbg) { + if (l[i].linenum == ln) { printf("find_line(): Found line number %u, at line index %X.\n", ln, i); } - } - if (dbg) { printf("find_line(): linenum: %u, i: %X\n", l[i].linenum, i); } return i; @@ -425,15 +410,22 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) { uint16_t symid = 0; uint16_t line = 0; lex_type = 0xFF; + uint8_t k = 0; + uint8_t ch = 0; uint8_t rs = 0; - uint8_t isop = 0; uint8_t base = 0; + + uint8_t isop = 0; int num = 0; int isch = 0; + uint8_t isesc = 0; + uint8_t islinenum; + int16_t ln = -1; + char lnum[6]; - uint8_t islinenum; + uint8_t space = 0; uint8_t tab = 0; uint8_t isstart = 1; @@ -505,11 +497,9 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) { lexeme[j] = '\0'; if (!isop) { for (k = 0; k < 6; k++) { - if (tolower(lexeme[0]) == dir_t[k][0]) { - if (!strcasecmp(lexeme, dir_t[k])) { - lex_type = TOK_DIR; - break; - } + if (tolower(lexeme[0]) == dir_t[k][0] && !strcasecmp(lexeme, dir_t[k])) { + lex_type = TOK_DIR; + break; } } l[line].dir = k; @@ -549,28 +539,18 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) { string[strid] = malloc(j+1); memcpy(string[strid], lexeme, j+1); l[line].str = strid; - if (dbg) { - printf("lex(): str[0x%04X]: %s\n", strid, string[strid]); - } stridx += (line == lineidx); } else { l[line].str = strid; - if (dbg) { - printf("lex(): str[0x%04X]: %s\n", strid, string[strid]); - } + } + if (dbg) { + printf("lex(): str[0x%04X]: %s\n", strid, string[strid]); } if (l[line].dir == DIR_INCLUDE) { l[line].incl = strid; } lex_type = TOK_STRING; break; - case '#': - lexeme[j] = '#'; - lexeme[j+1] = '\0'; - lexeme[j+2] = '\0'; - l[line].am = IMM; - lex_type = TOK_IMM; - break; if (str[i] == '$') { case '$': base = 16; } else if (str[i] == '%') { @@ -586,10 +566,10 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) { if (l[line].cm != 0xFF) { case TOK_PLUS : case TOK_MINUS: l[line].aop = strtoull(lexeme, NULL, base); - l[line].aopbase = (base & 16) ? TOK_HEX : TOK_BIN; + l[line].aopbase = (base & 16) ? BASE_HEX : BASE_BIN; } else { case TOK_SYM: l[line].op = strtoull(lexeme, NULL, base); - l[line].opbase = (base & 16) ? TOK_HEX : TOK_BIN; + l[line].opbase = (base & 16) ? BASE_HEX : BASE_BIN; } if (lex_type == TOK_SYM) { mksymbol(sym, l[line].op, 1, 0, 0, dbg); @@ -604,23 +584,59 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) { lex_type = (base & 16) ? TOK_HEX : TOK_BIN; break; - case '+': - lexeme[j] = '+'; - lexeme[j+1] = '\0'; - l[line].cm = 0; - lex_type = TOK_PLUS; - break; - case '-': - lexeme[j] = '-'; - lexeme[j+1] = '\0'; - l[line].cm = 1; - lex_type = TOK_MINUS; + case '\'': + i++; + k = j; + while (str[i] != '\'' || isesc) { + isesc = (str[i] == '\\' && str[i-1] != '\\'); + lexeme[j++] = str[i++]; + } + isesc = 0; + lexeme[j] = '\0'; + switch (lexeme[k]) { + case '\\': + switch (lexeme[++k]) { + case 'n' : ch = '\n'; break; + case 'r' : ch = '\r'; break; + case 'b' : ch = '\b'; break; + case '\'': ch = '\''; break; + case '\"': ch = '\"'; break; + case '\\': ch = '\\'; break; + } + break; + default: ch = lexeme[k]; + } + switch (lex_type) { + case TOK_PLUS : + case TOK_MINUS: + l[line].aop = ch; + l[line].aopbase = BASE_CHAR; + break; + default: + l[line].op = ch; + l[line].opbase = BASE_CHAR; + break; + } + lex_type = TOK_CHAR; break; case '(': - lexeme[j] = '('; - lexeme[j+1] = '\0'; - lexeme[j+2] = '\0'; - l[line].am = IND; + if (str[i] == '#' || str[i] == '(') { + if (str[i] == '#') { + case '#': lex_type = TOK_IMM; + } + l[line].am = (str[i] == '#') ? IMM : IND; + } else { + case '+': + case '-': l[line].cm = (str[i] == '-'); + lex_type = (str[i] == '-') ? TOK_MINUS : TOK_PLUS; + } + memset(lexeme, 0, strlen(lexeme)+1); + lexeme[j] = str[i]; + if (str[i] == '=') { + case '=': i++; + l[line].issym = 1; + lex_type = TOK_SYM; + } break; case ')': i++; @@ -679,13 +695,6 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) { printf("lex(): isfixup: %u\n", isfixup); } break; - case '=': - i++; - lexeme[j] = '='; - lexeme[j+1] = 0; - l[line].issym = 1; - lex_type = TOK_SYM; - break; case ';': i++; while (str[i] != '\0' && str[i] != '\n') { @@ -702,15 +711,12 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) { comment[comid] = malloc(j+1); memcpy(comment[comid], lexeme, j+1); l[line].com = comid; - if (dbg) { - printf("lex(): com[0x%04X]: %s\n", comid, comment[comid]); - } comidx += (line == lineidx); } else { l[line].com = comid; - if (dbg) { - printf("lex(): com[0x%04X]: %s\n", comid, comment[comid]); - } + } + if (dbg) { + printf("lex(): com[0x%04X]: %s\n", comid, comment[comid]); } lex_type = TOK_COMMENT; break; @@ -794,10 +800,10 @@ uint64_t lex(char *str, struct line *l, uint64_t address, uint8_t dbg) { if (l[line].cm != 0xFF) { case TOK_PLUS : case TOK_MINUS: l[line].aop = strtoull(lexeme, NULL, 10); - l[line].aopbase = TOK_DEC; + l[line].aopbase = BASE_DEC; } else { case TOK_SYM: l[line].op = strtoull(lexeme, NULL, 10); - l[line].opbase = TOK_DEC; + l[line].opbase = BASE_DEC; } if (lex_type == TOK_SYM) { mksymbol(sym, l[line].op, 1, 0, 0, dbg); diff --git a/programs/subeditor.s b/programs/subeditor.s index 1842b5a..d16915d 100644 --- a/programs/subeditor.s +++ b/programs/subeditor.s @@ -300,7 +300,7 @@ getchar: stb b ; Enable insert mode. pha #1 ; Save the character. phy #2 ; Save the cursor index. - cmp #10 ; Was the character that was typed, a newline? + cmp #'\n' ; Was the character that was typed, a newline? bne getchar_pnt ; No, so just print the character. jsl cmd_cpy ; Yes, so start copying the line to the command buffer. getchar_pnt: @@ -311,7 +311,7 @@ getchar_pnt: getchar_pt1: jsl print_char ; No, so print the character. lda a ; Get the return value. - cmp #10 ; Is the return value, a newline? + cmp #'\n' ; Is the return value, a newline? beq getchar_ln ; Yes, so return 0. jmp getchar_chr ; No, so return 1. reset_row: @@ -449,7 +449,7 @@ print_char: lda a ; Get back the character. cmp #$1B ; Did the user type an escape character? beq esc ; Yes, so go check the escape code. - cmp #10 ; No, but did the user type a newline? + cmp #'\n' ; No, but did the user type a newline? beq nl ; Yes, so handle the newline. cmp #$C ; No, but did the user type Ctrl+L? beq clr_scr ; Yes, so clear the screen. @@ -457,7 +457,7 @@ print_char: beq en_step ; Yes, so enable clock/instruction stepping. cmp #18 ; No, but did the user type Ctrl+R? beq dis_step ; Yes, so disable clock/instruction stepping. - cmp #8 ; No, but did the user type a backspace? + cmp #'\b' ; No, but did the user type a backspace? beq bs ; Yes, so handle the backspace. cmp #$7F ; No, but did they type Delete? beq bs ; Yes, so treat it as a backspace. @@ -571,13 +571,12 @@ nl1: cmp #maxrow ; bcc nl_inc ; jsl scrl_down ; - lda #10 ; - sta a ; - jmp printc_end ; + jmp nl_end ; nl_inc: inc scr_row ; jsl update_pos ; - lda #10 ; +nl_end: + lda #'\n' ; sta a ; jmp printc_end ; @@ -826,14 +825,14 @@ shftesc_end: jmp printc_end ; We are done. isup: - lda c ; No, so load the escape code back into the accumulator. - cmp #$41 ; Did the user press the up arrow key? + lda c ; Load the escape code into the accumulator. + cmp #'A' ; Did the user press the up arrow key? bne isup_done ; No, so we're done. lda scr_row ; Yes, but is the cursor at the top of the screen? beq isup_scrl ; Yes, so check if we need to scroll. isup_2: lda c ; No, so load the escape code back into the accumulator. - cmp #$41 ; Did the user press the up arrow key? + cmp #'A' ; Did the user press the up arrow key? beq up ; Yes, so move the cursor up. jmp isup_done ; No, so we're done isup_scrl: @@ -846,14 +845,14 @@ isup_done: rtl ; End of isup. isdown: - lda c ; No, so load the escape code back into the accumulator. - cmp #$42 ; Did the user press the down arrow key? + lda c ; Load the escape code into the accumulator. + cmp #'B' ; Did the user press the down arrow key? bne isdown_done ; No, so we're done. lda scr_row ; Yes, so start checking the y coordinate of the cursor. cmp #maxrow ; Is the cursor at the bottom of the screen? beq isdown_scrl ; Yes, so scroll down. lda c ; No, so load the escape code back into the accumulator. - cmp #$42 ; Did the user press the down arrow key? + cmp #'B' ; Did the user press the down arrow key? beq down ; Yes, so move the cursor down. jmp isdown_done isdown_scrl: @@ -872,8 +871,8 @@ isdown_done: rtl ; End of isdown. isright: - lda c ; No, so load the escape code back into the accumulator. - cmp #$43 ; Did the user press the right arrow key? + lda c ; Load the escape code into the accumulator. + cmp #'C' ; Did the user press the right arrow key? bne isright_dne ; No, so we're done. lda scr_col ; Yes, so start checking the x coordinate of the cursor. cmp #maxcol ; Is the cursor at the far right of the screen? @@ -910,13 +909,13 @@ isright_dne: rtl ; End of isright. isleft: - lda c ; Get the saved character. - cmp #$43 ; Did the user press right? + lda c ; Load the escape code into the accumulator. + cmp #'C' ; Did the user press right? beq isleft_done ; Yes, so we're done lda scr_col ; No, but is the cursor at the far left of the screen? beq isleft_wrp ; Yes, so start checking if this is a wrapped line. lda c ; No, so load the escape code back into the accumulator. - cmp #$44 ; Did the user press the left arrow key? + cmp #'D' ; Did the user press the left arrow key? beq left ; Yes, so move the cursor left. jmp isleft_done ; No, so we're done. isleft_wrp: @@ -976,7 +975,7 @@ left: isshftup: lda c ; Load the escape code back into the accumulator. - cmp #$41 ; Did the user press the up arrow key? + cmp #'A' ; Did the user press the up arrow key? bne shftup_done ; lda #1 ; sta d ; @@ -988,7 +987,7 @@ shftup_done: isshftdown: lda c ; Load the escape code back into the accumulator. - cmp #$42 ; Did the user press the down arrow key? + cmp #'B' ; Did the user press the down arrow key? bne shftdn_done ; lda #1 ; sta d ; @@ -1023,35 +1022,35 @@ update_pos: tay ; Place the index into the Y register. lda #$1B ; Print an escape character sta scr ; to the screen. - lda #$5B ; Print '[' + lda #'[' ; Print '[' sta scr ; to the screen, and start the escape sequence. jsl getrow ; Start printing the row number to the screen. jsl getcol ; Start printing the column number to the screen. - lda #$48 ; Print 'H' + lda #'H' ; Print 'H' sta scr ; to the screen. rtl ; End of update_pos. getrow: lda scr_row ; Get the cursor's y coordinate. div #10 ; Divide A by 10. - adc #$30 ; Convert it to ascii, and + adc #'0' ; Convert it to ascii, and sta scr ; print to the screen. tba ; Get the remainder. - adc #$30 ; Convert it to ascii, and + adc #'0' ; Convert it to ascii, and sta scr ; print to the screen. rtl ; End of getrow. getcol: - lda #$3B ; Print ';' + lda #';' ; Print ';' sta scr ; to the screen. lda scr_col ; Get the cursor's x coordinate. div #10 ; Divide A by 10. clc - adc #$30 ; Convert it to ascii, and + adc #'0' ; Convert it to ascii, and sta scr ; print to the screen. tba ; Get the remainder. clc - adc #$30 ; Convert it to ascii, and + adc #'0' ; Convert it to ascii, and sta scr ; print to the screen. rtl ; End of getrow. @@ -1060,9 +1059,9 @@ scrl_down: inc scr_end ; Increment the ending line of the screen. lda #$1B ; Print an escape character sta scr ; to the screen. - lda #$5B ; Print '[' + lda #'[' ; Print '[' sta scr ; to the screen, and start the escape sequence. - lda #$54 ; Print 'T' + lda #'T' ; Print 'T' sta scr ; to the screen, and end the escape sequence. lda scr_row ; Get the cursor's line number. pha #1 ; Save it in the stack. @@ -1094,9 +1093,9 @@ scrl_up: dec scr_end ; lda #$1B ; Print an escape character sta scr ; to the screen. - lda #$5B ; Print '[' + lda #'[' ; Print '[' sta scr ; to the screen, and start the escape sequence. - lda #$53 ; Print 'S' + lda #'S' ; Print 'S' sta scr ; to the screen, and end the escape sequence. lda scr_row ; pha #1 ; @@ -1133,7 +1132,7 @@ rdrow_inc2: bcs rdrow_end ; jmp rdrow_st ; rdrow_skip: - lda #$20 ; + lda #' ' ; sta scr ; to the screen. jmp rdrow_inc1 ; rdrow_end: diff --git a/test/lex.s b/test/lex.s index 543a3d8..037ce2b 100644 --- a/test/lex.s +++ b/test/lex.s @@ -1,7 +1,9 @@ ; aaaaaaaaaaaaaaaaa + SYM = $10 SYM1 = 10 SYM2 = %00000010 + .org $A000 ; String Literals/Constants. tok: @@ -12,6 +14,7 @@ string: .byte "Please, type something.\n" string2: .byte "You typed, " + .org $1000 lex: .byte $0 @@ -33,8 +36,16 @@ reset: sta lex, x ; same with this one sta $1000 ; lol lda.w #cmd_buf+8; + lda 'a' ; cool. + lda ' ' ; cool. + lda '\n' ; cool. + lda '\r' ; cool. + lda '\b' ; cool. + lda '\\' ; cool. + lda '\'' ; cool. +l a -.org $A000 +.org $8000 v q -- cgit v1.2.3-13-gbd6f