From 2090a4fd8ee743b7a3095c354bb0fbc14dbb1495 Mon Sep 17 00:00:00 2001 From: mrb0nk500 Date: Sat, 30 May 2020 12:43:08 -0400 Subject: Refactored the assembler a bit more, in order to remove code duplication. The assembler now uses pre-tokens, which are smaller tokens, that make up the larger tokens. --- asmmon.c | 2 +- asmmon.h | 53 ++++++--- lexer.c | 328 +++++++++++++++++++++++++----------------------------- lexer.h | 43 +++++++ programs/subasm.s | 137 ++--------------------- programs/utils.s | 136 ++++++++++++++++++++++ 6 files changed, 379 insertions(+), 320 deletions(-) create mode 100644 lexer.h create mode 100644 programs/utils.s diff --git a/asmmon.c b/asmmon.c index 840deae..f9fbd7a 100644 --- a/asmmon.c +++ b/asmmon.c @@ -4,6 +4,7 @@ uint16_t lineidx = 0; uint16_t stridx = 0; uint16_t comidx = 0; uint16_t inc_file = 0; /* Number of included files. */ +uint16_t inc_count = 0; uint8_t defined = 0; @@ -307,7 +308,6 @@ int asmmon(const char *fn) { uint8_t dbg = 0; uint8_t isinclude = 0; uint16_t tmp_lineidx = 0; - uint8_t inc_count = 0; init_symbol(); while (!done) { char *cmd; diff --git a/asmmon.h b/asmmon.h index 059d801..10c52e3 100644 --- a/asmmon.h +++ b/asmmon.h @@ -47,7 +47,7 @@ struct ln { struct ln *next; /* Pointer to the next line. */ struct tok *tok; /* The token(s) for this line. */ uint16_t count; /* Total tokens for this line. */ - uint16_t linenum; /* Line number. */ + uint32_t linenum; /* Line number. */ uint64_t addr; /* The address of this line. */ uint8_t stab; /* Number of starting tabs. */ uint8_t sspace; /* Number of starting spaces. */ @@ -101,9 +101,10 @@ enum token { TOK_LABEL, TOK_SYM, TOK_EXPR, - TOK_COMMA, + TOK_CSV, TOK_STRING, TOK_CHAR, + TOK_IND, TOK_IMM, TOK_OPCODE, TOK_RS, @@ -114,6 +115,30 @@ enum token { TOK_INCLUDE }; +enum proto_token { + PTOK_DOT, + PTOK_COLON, + PTOK_EQU, + PTOK_PLUS, + PTOK_MINUS, + PTOK_GT, + PTOK_LT, + PTOK_LBRACK, + PTOK_RBRACK, + PTOK_COMMA, + PTOK_X, + PTOK_Y, + PTOK_DQUOTE, + PTOK_SQUOTE, + PTOK_HASH, + PTOK_SCOLON, + PTOK_DOLLAR, + PTOK_PERCENT, + PTOK_NUMBER, + PTOK_ALPHA, + PTOK_OTHER +}; + enum expr { EXPR_PLUS, EXPR_MINUS, @@ -230,22 +255,23 @@ static const char *rs_t[4] = { [3] = ".q" }; -static const char *lex_tok[15] = { +static const char *lex_tok[16] = { [0x0] = "TOK_DIR", [0x1] = "TOK_LABEL", [0x2] = "TOK_SYM", [0x3] = "TOK_EXPR", - [0x4] = "TOK_COMMA", + [0x4] = "TOK_CSV", [0x5] = "TOK_STRING", [0x6] = "TOK_CHAR", - [0x7] = "TOK_IMM", - [0x8] = "TOK_OPCODE", - [0x9] = "TOK_RS", - [0xA] = "TOK_COMMENT", - [0xB] = "TOK_HEX", - [0xC] = "TOK_DEC", - [0xD] = "TOK_BIN", - [0xE] = "TOK_INCLUDE" + [0x7] = "TOK_IND", + [0x8] = "TOK_IMM", + [0x9] = "TOK_OPCODE", + [0xA] = "TOK_RS", + [0xB] = "TOK_COMMENT", + [0xC] = "TOK_HEX", + [0xD] = "TOK_DEC", + [0xE] = "TOK_BIN", + [0xF] = "TOK_INCLUDE" }; static const char *adrmode[9] = { @@ -466,6 +492,7 @@ extern uint16_t lineidx; extern uint16_t stridx; extern uint16_t comidx; extern uint16_t inc_file; /* Number of included files. */ +extern uint16_t inc_count; struct bc { uint64_t progsize; @@ -485,7 +512,7 @@ extern char *get_symname(uint16_t id, uint8_t dbg); extern uint16_t get_symid(const char *name, uint64_t val, token *t, uint8_t dbg); extern uint16_t get_comment(const char *cmnt, uint8_t dbg); extern uint16_t reslv_fixups(uint8_t dbg); -extern line *find_line(uint16_t ln, uint8_t dbg); +extern line *find_line(uint32_t ln, uint8_t dbg); extern uint64_t lex(char *str, uint64_t address, uint8_t dbg); extern uint64_t parse_tokens(token *tm, bytecount *bc, uint8_t isasm, uint64_t address, uint8_t dbg); diff --git a/lexer.c b/lexer.c index ea83801..9610297 100644 --- a/lexer.c +++ b/lexer.c @@ -1,4 +1,5 @@ #include "asmmon.h" +#include "lexer.h" uint8_t lex_type; uint16_t sym_count = 0; @@ -215,8 +216,8 @@ uint16_t reslv_fixups(uint8_t dbg) { } -line *find_line(uint16_t ln, uint8_t dbg) { - uint16_t i = 0; +line *find_line(uint32_t ln, uint8_t dbg) { + uint32_t i = 0; line *l = lines; for (; l && l->linenum != ln; l = l->next); /*if (dbg) { @@ -276,7 +277,7 @@ uint64_t lex(char *str, uint64_t address, uint8_t dbg) { token *t = NULL; token *lt = NULL; - while (isdigit(str[i]) && !isspace(str[i])) { + while (isdigit(str[i]) && isdelm(str[i], dbg) != 16) { lnum[j++] = str[i++]; } islinenum = i; @@ -284,10 +285,11 @@ uint64_t lex(char *str, uint64_t address, uint8_t dbg) { lnum[j] = '\0'; ln = strtol(lnum, NULL, 10); j = 0; + l = find_line(ln, dbg); } else { ln = linenum; + l = NULL; } - l = find_line(ln, dbg); if (l) { address = l->addr; } else { @@ -299,11 +301,11 @@ uint64_t lex(char *str, uint64_t address, uint8_t dbg) { last_line = l; } - while (str[i] != '\0' && str[i] != '\n') { + while (isdelm(str[i], dbg) != 1) { base = 0; space = 0; tab = 0; - while (isspace(str[i+j])) { + while (isdelm(str[i+j], dbg) == 16) { tab += str[i+j] == '\t'; space += str[i+j] == ' '; j++; @@ -319,18 +321,23 @@ uint64_t lex(char *str, uint64_t address, uint8_t dbg) { printf("lex(): starting tabs: %u, starting spaces: %u\n", l->stab, l->sspace); } } - if (isspace(str[i])) { - while (isspace(str[i])) { - i++; + if (isdelm(str[i], dbg) == 16) { + for (; isdelm(str[i], dbg) == 16; i++); + } + uint8_t ptok = get_ptok(str[i], dbg); + if (ptok == PTOK_X || ptok == PTOK_Y) { + switch (get_ptok(str[i+1], dbg)) { + case PTOK_ALPHA : + case PTOK_NUMBER: ptok = PTOK_ALPHA; break; } } - switch (str[i]) { - case '.': + switch (ptok) { + case PTOK_DOT: i++; - while (!isspace(str[i])) { - lexeme[j++] = str[i++]; - } + for (; isdelm(str[i+j], dbg) != 16; j++); + memcpy(lexeme, str+i, j); lexeme[j] = '\0'; + i += j; if (!isop) { for (k = 0; k < 6; k++) { if (tolower(lexeme[0]) == dir_t[k][0] && !strcasecmp(lexeme, dir_t[k])) { @@ -361,11 +368,12 @@ uint64_t lex(char *str, uint64_t address, uint8_t dbg) { isop = 0; } break; - case '\"': + case PTOK_DQUOTE: i++; - while (str[i] != '\"') { - lexeme[j++] = str[i++]; - } + for (; isdelm(str[i+j], dbg) != 4; j++); + memcpy(lexeme, str+i, j); + lexeme[j] = '\0'; + i += j; strid = get_string(lexeme, dbg); if (strid == 0xFFFF) { strid = stridx; @@ -378,22 +386,26 @@ uint64_t lex(char *str, uint64_t address, uint8_t dbg) { printf("lex(): str[0x%04X]: %s\n", strid, string[strid]); } if (lt->id == TOK_DIR && lt->type == DIR_INCLUDE) { - incl[inc_file++] = strid; + incl[inc_count] = strid; + inc_file++; } lex_type = TOK_STRING; l->count++; t = make_token(lex_type, 0, 0, string[strid]); break; - case '$': - case '%': + case PTOK_DOLLAR: + case PTOK_PERCENT: + case PTOK_NUMBER: value = 0; - base = (str[i] == '$') ? 16 : 2; - i++; - while (isxdigit(str[i]) && (str[i] != '\0' && str[i] != '\n' && str[i] != ',')) { - lexeme[j++] = str[i++]; + switch (ptok) { + case PTOK_DOLLAR : base = 16; lex_type = TOK_HEX; i++; break; + case PTOK_PERCENT: base = 2; lex_type = TOK_BIN; i++; break; + case PTOK_NUMBER : base = 10; lex_type = TOK_DEC; /**/ break; } + for (; isxdigit(str[i+j]) && !(isdelm(str[i+j], dbg) & 0x03); j++); + memcpy(lexeme, str+i, j); lexeme[j] = '\0'; - lex_type = (base == 16) ? TOK_HEX : TOK_BIN; + i += j; value = strtoull(lexeme, NULL, base); if (lt->id == TOK_SYM) { mksymbol(sym, value, 1, 0, 0, dbg); @@ -408,10 +420,10 @@ uint64_t lex(char *str, uint64_t address, uint8_t dbg) { l->count++; t = make_token(lex_type, 0, value, ""); break; - case '\'': + case PTOK_SQUOTE: i++; k = j; - while (str[i] != '\'' || isesc) { + while (isdelm(str[i], dbg) != 8 || isesc) { isesc = (str[i] == '\\' && str[i-1] != '\\'); lexeme[j++] = str[i++]; } @@ -434,25 +446,25 @@ uint64_t lex(char *str, uint64_t address, uint8_t dbg) { l->count++; t = make_token(lex_type, 0, ch, ""); break; - case '(': l->tok->type = IND; memset(lexeme, 0, strlen(lexeme)+1); lexeme[j++] = str[i]; break; - case '#': l->tok->type = IMM; memset(lexeme, 0, strlen(lexeme)+1); lexeme[j++] = str[i]; break; - case '+': - case '-': - case '>': - case '<': + case PTOK_LBRACK: l->tok->type = IND; memset(lexeme, 0, strlen(lexeme)+1); lexeme[j++] = str[i]; break; + case PTOK_HASH : l->tok->type = IMM; memset(lexeme, 0, strlen(lexeme)+1); lexeme[j++] = str[i]; break; + case PTOK_PLUS: + case PTOK_MINUS: + case PTOK_GT: + case PTOK_LT: lex_type = TOK_EXPR; - switch (str[i]) { - case '+': value = EXPR_PLUS ; break; - case '-': value = EXPR_MINUS; break; - case '>': value = EXPR_LOW ; break; - case '<': value = EXPR_HIGH ; break; + switch (ptok) { + case PTOK_PLUS : value = EXPR_PLUS ; break; + case PTOK_MINUS: value = EXPR_MINUS; break; + case PTOK_GT : value = EXPR_LOW ; break; + case PTOK_LT : value = EXPR_HIGH ; break; } l->count++; t = make_token(lex_type, value, 0, ""); memset(lexeme, 0, strlen(lexeme)+1); lexeme[j++] = str[i]; break; - case '=': + case PTOK_EQU: i++; lex_type = TOK_SYM; l->count++; @@ -460,49 +472,34 @@ uint64_t lex(char *str, uint64_t address, uint8_t dbg) { memset(lexeme, 0, strlen(lexeme)+1); lexeme[j] = str[i]; break; - case ')': + case PTOK_RBRACK: i++; - if (str[i] == ',') { - i++; - while (isspace(str[i])) { - lexeme[j++] = str[i++]; - } - if (l->tok->type == IND && tolower(str[i]) == 'y') { - lexeme[j++] = 'y'; - l->tok->type = INDY; - } - lexeme[j] = '\0'; - } else { - lexeme[j] = ')'; - lexeme[j+1] = '\0'; - lexeme[j+2] = '\0'; - } + lex_type = TOK_IND; + lexeme[j] = ')'; + lexeme[j+1] = '\0'; + lexeme[j+2] = '\0'; break; - case ',': + case PTOK_COMMA: i++; - while (isspace(str[i])) { - lexeme[j++] = str[i++]; + if (lex_type != TOK_IND) { + lex_type = TOK_CSV; } - if (l->tok->type == IND && tolower(str[i]) == 'x') { - l->tok->type = INDX; - lexeme[j++] = 'x'; - i++; - } else { - switch (tolower(str[i])) { - case 'x': - l->tok->type = ZMX; - lexeme[j++] = 'x'; - break; - case 'y': - l->tok->type = ZMY; - lexeme[j++] = 'y'; - break; - default: lex_type = TOK_COMMA; i--; break; - } + lexeme[j] = ','; + lexeme[j+1] = '\0'; + lexeme[j+2] = '\0'; + break; + case PTOK_X: + case PTOK_Y: + switch (ptok) { + case PTOK_X: l->tok->type = (lex_type == TOK_IND) ? INDX : ZMX; break; + case PTOK_Y: l->tok->type = (lex_type == TOK_IND) ? INDY : ZMY; break; } - lexeme[j] = '\0'; + lexeme[j] = str[i]; + lexeme[j+1] = '\0'; + lexeme[j+2] = '\0'; + i++; break; - case ':': + case PTOK_COLON: i++; lexeme[j] = ':'; lexeme[j+1] = '\0'; @@ -519,12 +516,12 @@ uint64_t lex(char *str, uint64_t address, uint8_t dbg) { printf("lex(): isfixup: %u\n", isfixup); } break; - case ';': + case PTOK_SCOLON: i++; - while (str[i] != '\0' && str[i] != '\n') { - lexeme[j++] = str[i++]; - } + for (; isdelm(str[i+j], dbg) != 1; j++); + memcpy(lexeme, str+i, j); lexeme[j] = '\0'; + i += j; comid = get_comment(lexeme, dbg); if (comid == 0xFFFF) { /*if (line != lineidx && l[line].com != 0xFFFF) { @@ -545,118 +542,88 @@ uint64_t lex(char *str, uint64_t address, uint8_t dbg) { l->count++; t = make_token(lex_type, 0, 0, comment[comid]); break; - default: - if (isalnum(str[i]) || str[i] == '_') { - while (!isspace(str[i])) { - switch (str[i]) { + case PTOK_ALPHA: + while (isdelm(str[i], dbg) != 16) { + switch (str[i]) { + case ')': + case ',': + case '.': + case '+': + case '<': + case '>': + case '-': + case ':': + case '=': + case ';': + case '\0': + case '\n': + isch = 0; + break; + default: + isch = 1; + lexeme[j++] = str[i++]; + break; + } + if (!isch) { + break; + } + } + lexeme[j] = '\0'; + isch = 0; + isop = 0; + if (j == 3 && str[i] != ':') { + for (k = 0; k < OPNUM; k++) { + if (toupper(lexeme[0]) == mne[k][0]) { + if (!strcasecmp(lexeme, mne[k])) { + lex_type = TOK_OPCODE; + isop = 1; + l->count++; + t = make_token(lex_type, 0xFF, k, ""); + break; + } + } + } + } + if (!isop) { + for (k = 0; lexeme[k] != '\0';) { + switch (lexeme[k]) { case ')': case ',': case '.': case '+': + case '-': case '<': case '>': - case '-': case ':': - case '=': case ';': + case '=': case '\0': case '\n': - isch = 0; + fall = 1; break; default: - isch = 1; - lexeme[j++] = str[i++]; + fall = 0; break; } - if (!isch) { + if (fall) { break; } + k++; } - lexeme[j] = '\0'; - isch = 0; - isop = 0; - if (j == 3 && str[i] != ':') { - for (k = 0; k < OPNUM; k++) { - if (toupper(lexeme[0]) == mne[k][0]) { - if (!strcasecmp(lexeme, mne[k])) { - lex_type = TOK_OPCODE; - isop = 1; - l->count++; - t = make_token(lex_type, 0xFF, k, ""); - break; - } - } - } + lex_type = TOK_SYM; + l->count++; + t = make_token(lex_type, 0, 0, ""); + memcpy(sym, lexeme, j+1); + uint8_t spaces = 0; + for (; isdelm(str[i+spaces], dbg) == 16; spaces++); + if (dbg) { + printf("lex(): spaces: %u\n", spaces); } - if (!isop) { - for (k = 0; lexeme[k] != '\0';) { - switch (lexeme[k]) { - case ')': - case ',': - case '.': - case '+': - case '-': - case '<': - case '>': - case ':': - case ';': - case '=': - case '\0': - case '\n': - fall = 1; - break; - default: - fall = 0; - break; - } - if (fall) { - break; - } - if ((isalnum(lexeme[k]) || lexeme[k] == '_')) { - if (!isch) { - isch = isalpha(lexeme[k]); - } - num = isdigit(lexeme[k]) && !isch; - k++; - } else { - break; - } - } - if (lexeme[k] == '\0') { - if (num) { - value = 0; - value = strtoull(lexeme, NULL, 10); - if (lt->id == TOK_SYM) { - mksymbol(sym, value, 1, 0, 0, dbg); - if (lt) { - lt->word = get_symid(sym, address, lt, dbg); - } - isfixup += (lt->word == 0xFFFF); - if (dbg) { - printf("lex(): isfixup: %u\n", isfixup); - } - } - lex_type = TOK_DEC; - l->count++; - t = make_token(lex_type, 0, value, ""); - } else if (isch && lex_type != TOK_HEX && lex_type != TOK_BIN) { - lex_type = TOK_SYM; - l->count++; - t = make_token(lex_type, 0, 0, ""); - memcpy(sym, lexeme, j+1); - uint8_t spaces = 0; - for (; isspace(str[i+spaces]); spaces++); - if (dbg) { - printf("lex(): spaces: %u\n", spaces); - } - if (str[i+spaces] != ':' && str[i+spaces] != '=') { - t->word = get_symid(lexeme, address, t, dbg); - isfixup += (t->word == 0xFFFF); - if (dbg) { - printf("lex(): isfixup: %u\n", isfixup); - } - } - } + if (str[i+spaces] != ':' && str[i+spaces] != '=') { + t->word = get_symid(lexeme, address, t, dbg); + isfixup += (t->word == 0xFFFF); + if (dbg) { + printf("lex(): isfixup: %u\n", isfixup); } } } @@ -707,9 +674,14 @@ uint64_t lex(char *str, uint64_t address, uint8_t dbg) { } } } - if (lex_type != TOK_SYM) { - memset(lexeme, 0, strlen(lexeme)+1); - lex_type = 0xFF; + switch (lex_type) { + default: + lex_type = 0xFF; + case TOK_CSV: + case TOK_IND: + memset(lexeme, 0, strlen(lexeme)+1); + case TOK_SYM: + break; } if (t) { lt = t; diff --git a/lexer.h b/lexer.h new file mode 100644 index 0000000..b8b14b0 --- /dev/null +++ b/lexer.h @@ -0,0 +1,43 @@ +static inline uint8_t isdelm(char c, uint8_t dbg) { + switch (c) { + default : return 0x00; + case '\0': + case '\n': return 0x01; + case ',' : return 0x02; + case '\"': return 0x04; + case '\'': return 0x08; + case '\t': + case ' ' : return 0x10; + } +} + +static inline uint8_t get_ptok(char c, uint8_t dbg) { + switch (c) { + case '.' : return PTOK_DOT ; + case ':' : return PTOK_COLON ; + case '=' : return PTOK_EQU ; + case '+' : return PTOK_PLUS ; + case '-' : return PTOK_MINUS ; + case '>' : return PTOK_GT ; + case '<' : return PTOK_LT ; + case '(' : return PTOK_LBRACK ; + case ')' : return PTOK_RBRACK ; + case ',' : return PTOK_COMMA ; + case 'X': case 'x' : return PTOK_X ; + case 'Y': case 'y' : return PTOK_Y ; + case '\"': return PTOK_DQUOTE ; + case '\'': return PTOK_SQUOTE ; + case '#' : return PTOK_HASH ; + case ';' : return PTOK_SCOLON ; + case '$' : return PTOK_DOLLAR ; + case '%' : return PTOK_PERCENT; + default : + if (isdigit(c)) { + return PTOK_NUMBER; + } else if (isalpha(c) || c == '_') { + return PTOK_ALPHA; + } else { + return PTOK_OTHER; + } + } +} diff --git a/programs/subasm.s b/programs/subasm.s index e5d620f..86a8837 100644 --- a/programs/subasm.s +++ b/programs/subasm.s @@ -5,6 +5,8 @@ MAX_SYM = $800 ; Max symbol size. +.include "utils.s" + .org incl ; String Constants. asm_name: @@ -150,9 +152,8 @@ cmd_srt: .word run .word set -; Hex character table. -hex_char: - .byte "0123456789ABCDEF" +; Data entry point for utility subroutines. +util_data: ; Token table. @@ -283,131 +284,6 @@ shcmd_end: ply #2 ; Get back the screen buffer position. rts ; End of chk_shcmd. -print_hex: - pha #8 ; Preserve the hex value. - and #0 ; Reset A. - ldb #1 ; Set the second pointer - lda.w #hex_char ; to the start of hex character table. - jsr set_ptr ; - inb ; Set the third pointer - lda.d #hex_str ; to the end of hex string buffer. - clc ; Do a non carrying add. - adc #$10 ; - jsr set_ptr ; - ldb #0 ; Reset B. - pla #8 ; Get the hex value back. -pnthex_lp: - pha #8 ; Preserve the hex value. - and #$F ; Mask the lowest nibble. - phy #2 ; Preserve the screen buffer position. - tay ; Get the index for the hex digit. - lda (ptr2), y ; Get the hex digit. - dec ptr3 ; Decrement the string pointer. - sta (ptr3) ; Save the hex digit character in the string. - ply #2 ; Get back the screen buffer position. - pla #8 ; Get the hex value back. -pnthex_lp1: - cpx #1 ; Is the digit count less than one? - bcc pnthex_lp2 ; Yes, so don't decrement the digit count. - dex ; No, but was the digit count zero, when decremented? - beq pnthex_end ; Yes, so we're done. - jmp pnthex_lp3 ; No, so get the next nibble. -pnthex_lp2: - ldb #1 ; Enable auto digit count. -pnthex_lp3: - lsr #4 ; No, but is the next nibble, a zero? - beq pnthex_lp4 ; Yes, so check if auto digit count is enabled. - jmp pnthex_lp ; No, so print the next digit. -pnthex_lp4: - cpb #1 ; Is auto digit count enabled? - beq pnthex_end ; Yes, so we're done. - jmp pnthex_lp ; No, so keep printing more digits. -pnthex_end: - rts ; End of print_hex. - -charcpy: - ldx idx3 ; Get the string index. - sta strbuf, x ; Save it in the string buffer. - inc idx3 ; Increment the string index. - rts ; End of charcpy. - -print_hi: - and #0 ; Reset A. - sta idx3 ; Clear the string index. - lda #'$' ; Print the hex delimiter. - jsr charcpy ; - lda.q idx0 ; Get the masked address. - ldx #$10 ; Set digit count to 16. - jsr print_hex ; Print the address. - lda.q hex_str ; Get the lower half of the string. - sta.q strbuf+1 ; Save it in the string buffer. - lda.q hex_str+8 ; Get the upper half of the string. - sta.q strbuf+9 ; Save it in the string buffer. - ldx #$11 ; Add 16 to the index. - stx idx3 ; - lda #':' ; Print a colon. - jsr charcpy ; - lda # ' ' ; Print a space. - jsr charcpy ; - rts ; End of print_hi. - -print_lo: - lda #0 ; Reset A. - sta idx3 ; Clear the string index. -pntlo_lp: - ldx #2 ; Set digit count to 2. - pha #1 ; Preserve the nibble offset. - jsr print_hex ; Print the low nibble offset. - lda.w (ptr3) ; Get the two digits. - jsr charcpy ; Copy the first digit. - lsr #8 ; Copy the next digit. - jsr charcpy ; - pla #1 ; Get the nibble offset back. - inc ; Increment the offset. - cmp #$10 ; Are we at the last offset? - bcs pntlo_end ; Yes, so we're done. -pntlo_lp1: - pha #1 ; No, so preserve the nibble offset. - lda #' ' ; Add a space to the string buffer. - jsr charcpy ; - pla #1 ; Get the nibble offset back. - jmp pntlo_lp ; Keep looping. -pntlo_end: - inx ; Increment the index by one. - lda #0 ; Null terminate the string buffer. - sta strbuf, x ; - tax ; Reset X. - lda.d #strbuf ; Print the string buffer. - jsr print_str ; - rts ; End of print_lo. - -print_chunk: - ldx #0 ; Reset X. - phy #2 ; Preserve the screen buffer index. - txy ; Copy the byte index to it. -pntchnk_lp: - and #0 ; Reset A. - ldx #2 ; Set the digit count to 2. - lda (idx0), y ; Get the byte at that address. - jsr print_hex ; Print the byte. - lda.w (ptr3) ; Get the two digits. - jsr charcpy ; Copy the first digit. - lsr #8 ; Copy the next digit. - jsr charcpy ; - iny ; Increment the byte index. - cpy #$10 ; Have we read 16 bytes? - beq pntchnk_end ; Yes, so we're done. - lda #' ' ; No, so add a soace to the string buffer. - jsr charcpy ; - jmp pntchnk_lp ; Keep looping. -pntchnk_end: - ply #2 ; Get the screen buffer index back. - inx ; Increment the index by one. - and #0 ; Null terminate the string. - sta strbuf, x ; - tax ; Reset X. - sta idx3 ; Clear the string index. - rts ; End of print_chunk. viewmem: lda.q prg_cnt ; Get the program counter. @@ -469,3 +345,8 @@ set: nop ; set_end: rts ; End of set. + + +; Entry point for utility subroutines. +utils: + diff --git a/programs/utils.s b/programs/utils.s new file mode 100644 index 0000000..a6a14f3 --- /dev/null +++ b/programs/utils.s @@ -0,0 +1,136 @@ +; Utility subroutines for SuBAsm. + +.org util_data +; Hex character table. +hex_char: + .byte "0123456789ABCDEF" + +.org utils + +print_hi: + and #0 ; Reset A. + sta idx3 ; Clear the string index. + lda #'$' ; Print the hex delimiter. + jsr charcpy ; + lda.q idx0 ; Get the masked address. + ldx #$10 ; Set digit count to 16. + jsr print_hex ; Print the address. + lda.q hex_str ; Get the lower half of the string. + sta.q strbuf+1 ; Save it in the string buffer. + lda.q hex_str+8 ; Get the upper half of the string. + sta.q strbuf+9 ; Save it in the string buffer. + ldx #$11 ; Add 16 to the index. + stx idx3 ; + lda #':' ; Print a colon. + jsr charcpy ; + lda # ' ' ; Print a space. + jsr charcpy ; + rts ; End of print_hi. + +print_lo: + lda #0 ; Reset A. + sta idx3 ; Clear the string index. +pntlo_lp: + ldx #2 ; Set digit count to 2. + pha #1 ; Preserve the nibble offset. + jsr print_hex ; Print the low nibble offset. + lda.w (ptr3) ; Get the two digits. + jsr charcpy ; Copy the first digit. + lsr #8 ; Copy the next digit. + jsr charcpy ; + pla #1 ; Get the nibble offset back. + inc ; Increment the offset. + cmp #$10 ; Are we at the last offset? + bcs pntlo_end ; Yes, so we're done. +pntlo_lp1: + pha #1 ; No, so preserve the nibble offset. + lda #' ' ; Add a space to the string buffer. + jsr charcpy ; + pla #1 ; Get the nibble offset back. + jmp pntlo_lp ; Keep looping. +pntlo_end: + inx ; Increment the index by one. + lda #0 ; Null terminate the string buffer. + sta strbuf, x ; + tax ; Reset X. + lda.d #strbuf ; Print the string buffer. + jsr print_str ; + rts ; End of print_lo. + +print_chunk: + ldx #0 ; Reset X. + phy #2 ; Preserve the screen buffer index. + txy ; Copy the byte index to it. +pntchnk_lp: + and #0 ; Reset A. + ldx #2 ; Set the digit count to 2. + lda (idx0), y ; Get the byte at that address. + jsr print_hex ; Print the byte. + lda.w (ptr3) ; Get the two digits. + jsr charcpy ; Copy the first digit. + lsr #8 ; Copy the next digit. + jsr charcpy ; + iny ; Increment the byte index. + cpy #$10 ; Have we read 16 bytes? + beq pntchnk_end ; Yes, so we're done. + lda #' ' ; No, so add a soace to the string buffer. + jsr charcpy ; + jmp pntchnk_lp ; Keep looping. +pntchnk_end: + ply #2 ; Get the screen buffer index back. + inx ; Increment the index by one. + and #0 ; Null terminate the string. + sta strbuf, x ; + tax ; Reset X. + sta idx3 ; Clear the string index. + rts ; End of print_chunk. + + +print_hex: + pha #8 ; Preserve the hex value. + and #0 ; Reset A. + ldb #1 ; Set the second pointer + lda.w #hex_char ; to the start of hex character table. + jsr set_ptr ; + inb ; Set the third pointer + lda.d #hex_str ; to the end of hex string buffer. + clc ; Do a non carrying add. + adc #$10 ; + jsr set_ptr ; + ldb #0 ; Reset B. + pla #8 ; Get the hex value back. +pnthex_lp: + pha #8 ; Preserve the hex value. + and #$F ; Mask the lowest nibble. + phy #2 ; Preserve the screen buffer position. + tay ; Get the index for the hex digit. + lda (ptr2), y ; Get the hex digit. + dec ptr3 ; Decrement the string pointer. + sta (ptr3) ; Save the hex digit character in the string. + ply #2 ; Get back the screen buffer position. + pla #8 ; Get the hex value back. +pnthex_lp1: + cpx #1 ; Is the digit count less than one? + bcc pnthex_lp2 ; Yes, so don't decrement the digit count. + dex ; No, but was the digit count zero, when decremented? + beq pnthex_end ; Yes, so we're done. + jmp pnthex_lp3 ; No, so get the next nibble. +pnthex_lp2: + ldb #1 ; Enable auto digit count. +pnthex_lp3: + lsr #4 ; No, but is the next nibble, a zero? + beq pnthex_lp4 ; Yes, so check if auto digit count is enabled. + jmp pnthex_lp ; No, so print the next digit. +pnthex_lp4: + cpb #1 ; Is auto digit count enabled? + beq pnthex_end ; Yes, so we're done. + jmp pnthex_lp ; No, so keep printing more digits. +pnthex_end: + rts ; End of print_hex. + + +charcpy: + ldx idx3 ; Get the string index. + sta strbuf, x ; Save it in the string buffer. + inc idx3 ; Increment the string index. + rts ; End of charcpy. -- cgit v1.2.3-13-gbd6f