summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormrb0nk500 <b0nk@b0nk.xyz>2020-05-30 12:43:08 -0400
committermrb0nk500 <b0nk@b0nk.xyz>2020-05-30 12:43:08 -0400
commit2090a4fd8ee743b7a3095c354bb0fbc14dbb1495 (patch)
tree7d6db28a62c669959430d375308111bb3439547d
parent2f9d38f9f9d6f17bc274934b23915417012eeed8 (diff)
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.
-rw-r--r--asmmon.c2
-rw-r--r--asmmon.h53
-rw-r--r--lexer.c328
-rw-r--r--lexer.h43
-rw-r--r--programs/subasm.s137
-rw-r--r--programs/utils.s136
6 files changed, 379 insertions, 320 deletions
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.