MOT6502 assembler, disassembler and linker
Revisión | 4d828c8878ac64dfaab024b72c18fc8087a18e2e (tree) |
---|---|
Tiempo | 2013-02-08 20:21:00 |
Autor | astoria-d <astoria-d@my-s...> |
Commiter | astoria-d |
assembler addressing mode fix.
now hello world assembler is verified.
@@ -17,6 +17,8 @@ struct instmap { | ||
17 | 17 | #define NUM_ALPHA 'Z' - 'A' + 1 |
18 | 18 | #define ALPHA_INDEX(ch) ch - 'A' |
19 | 19 | |
20 | +#define ROM_START 0x8000 | |
21 | + | |
20 | 22 | /* |
21 | 23 | * 6502 instructions |
22 | 24 | * adressing mode instruction length |
@@ -128,6 +130,10 @@ int get_rel_addr(unsigned short abs_addr) { | ||
128 | 130 | return (int) abs_addr - get_current_pc() ; |
129 | 131 | } |
130 | 132 | |
133 | +int get_abs_addr(unsigned short abs_addr) { | |
134 | + return (int) abs_addr + ROM_START ; | |
135 | +} | |
136 | + | |
131 | 137 | /* |
132 | 138 | * returns the length of opcode. |
133 | 139 | * returns 0 if invalid. |
@@ -388,11 +394,13 @@ static void deb_print_str(const char* str) { | ||
388 | 394 | } |
389 | 395 | |
390 | 396 | void write_str(const char* str) { |
397 | + //dprint("write_str:%s\n", str); | |
391 | 398 | int len = strlen(str) + 1; |
392 | 399 | FILE* fp = get_current_file(); |
400 | + char* p = str; | |
393 | 401 | while (len-- > 0) |
394 | 402 | fwrite(str++, 1, 1, fp); |
395 | - deb_print_str(str); | |
403 | + deb_print_str(p); | |
396 | 404 | move_current_pc(len); |
397 | 405 | } |
398 | 406 |
@@ -15,6 +15,7 @@ char* cur_inst; | ||
15 | 15 | int dir_data_size = 0; |
16 | 16 | |
17 | 17 | void add_unresolved_ref(const char* symbol); |
18 | +int get_abs_addr(unsigned short abs_addr); | |
18 | 19 | |
19 | 20 | #if 1 |
20 | 21 | #define dprint(...) |
@@ -205,6 +206,12 @@ inst_param | ||
205 | 206 | unsigned short addr = 0; |
206 | 207 | int num = 0; |
207 | 208 | |
209 | + | |
210 | + /* | |
211 | + ex) | |
212 | + lda palettes, x | |
213 | + */ | |
214 | + | |
208 | 215 | //second parameter is either X or Y. |
209 | 216 | if (strcasecmp($<str>3, "X") && strcasecmp($<str>3, "Y")) { |
210 | 217 | parser_perror("invalid parameter\n", $<str>3); |
@@ -218,11 +225,13 @@ inst_param | ||
218 | 225 | param = PARAM_NUM; |
219 | 226 | ch = toupper(*$<str>3); |
220 | 227 | param |= (ch == 'X' ? PARAM_INDEX_X : PARAM_INDEX_Y); |
221 | - if (addr_lookup($<str>1, &addr)) | |
222 | - num = get_rel_addr(addr); | |
228 | + if (addr_lookup($<str>1, &addr)) { | |
229 | + //reladdr from the next instruction. | |
230 | + num = get_rel_addr(addr) - 2; | |
231 | + } | |
223 | 232 | else { |
224 | 233 | add_unresolved_ref($<str>1); |
225 | - num = addr; | |
234 | + num = 0xFFFF; | |
226 | 235 | } |
227 | 236 | |
228 | 237 | if (!write_inst(cur_inst, param, num)) { |
@@ -288,12 +297,28 @@ inst_param | ||
288 | 297 | unsigned short addr = 0; |
289 | 298 | int num = 0; |
290 | 299 | |
300 | + /* | |
301 | + ex) | |
302 | + mainloop: | |
303 | + jmp mainloop | |
304 | + bne mainloop | |
305 | + */ | |
306 | + | |
291 | 307 | dprint("%s\n", $<str>1); |
292 | - if (addr_lookup($<str>1, &addr)) | |
293 | - num = get_rel_addr(addr); | |
308 | + if (addr_lookup($<str>1, &addr)) { | |
309 | + //set operand assocating with the instruction's addressing mode | |
310 | + //(relative or absolute). | |
311 | + if (!strcasecmp(cur_inst, "JMP") || !strcasecmp(cur_inst, "JSR")) { | |
312 | + num = get_abs_addr(addr); | |
313 | + } | |
314 | + else { | |
315 | + //reladdr from the next instruction. | |
316 | + num = get_rel_addr(addr) - 2; | |
317 | + } | |
318 | + } | |
294 | 319 | else { |
295 | 320 | add_unresolved_ref($<str>1); |
296 | - num = addr; | |
321 | + num = 0xFFFF; | |
297 | 322 | } |
298 | 323 | |
299 | 324 | if (!write_inst(cur_inst, PARAM_NUM, num)) { |
@@ -24,6 +24,7 @@ const char* get_out_fname(void); | ||
24 | 24 | void molf_header_create(FILE* fp, unsigned short seg_cnt); |
25 | 25 | void seg_header_create(FILE* fp, struct seginfo* seg); |
26 | 26 | int set_seg_header_pos(FILE* fp, struct seginfo* seg, unsigned short start); |
27 | +int get_abs_addr(unsigned short abs_addr); | |
27 | 28 | |
28 | 29 | int add_symbol (const char* symbol) { |
29 | 30 | struct symmap *psym, *pp; |
@@ -70,7 +71,9 @@ void add_unresolved_ref(const char* symbol) { | ||
70 | 71 | unres_sym = malloc(sizeof (struct symmap)); |
71 | 72 | dlist_init(&unres_sym->list); |
72 | 73 | unres_sym->symbol = strdup(symbol); |
73 | - unres_sym->addr = pseg->current_pc; | |
74 | + //current_pc points to the current instruction. | |
75 | + //referece is next to the pc | |
76 | + unres_sym->addr = pseg->current_pc + 1; | |
74 | 77 | |
75 | 78 | if (pseg->unresolved_symbol == NULL) { |
76 | 79 | pseg->unresolved_symbol = unres_sym; |
@@ -91,6 +94,8 @@ int addr_lookup(const char* symbol, unsigned short* return_addr) { | ||
91 | 94 | struct symmap* pp = psym; |
92 | 95 | |
93 | 96 | if (!strcmp(symbol, psym->symbol)) { |
97 | + dprint("addr_lookup %s found %04x, current:%08x\n", psym->symbol, | |
98 | + psym->addr, get_current_pc()); | |
94 | 99 | found = TRUE; |
95 | 100 | *return_addr = psym->addr; |
96 | 101 | break; |
@@ -257,9 +262,10 @@ int finalize_segment(void) { | ||
257 | 262 | //address offset is too far! |
258 | 263 | return FALSE; |
259 | 264 | } |
260 | - /*dprint("symbol ref at %04x to %s(%04x) resolved, %04x.\n", | |
261 | - unres->addr, unres->symbol, addr, addr - unres->addr);*/ | |
262 | - fseek(fp, addr - unres->addr, SEEK_SET); | |
265 | + addr = get_abs_addr(addr); | |
266 | + dprint("symbol ref at %04x to %s resolved, %04x.\n", | |
267 | + unres->addr, unres->symbol, addr);/**/ | |
268 | + fseek(fp, unres->addr, SEEK_SET); | |
263 | 269 | fwrite(&addr, 2, 1, fp); |
264 | 270 | } |
265 | 271 | unres = (struct symmap*) unres->list.next; |