P
Peter Karlsson
Hi gang,
My job description recently changed to include C coding, so I've got
to speed learn C. Anyway, I would be grateful for comments of
this little exercise I hacked up.
First, Splint 3.1.1 --- 13 Oct 2004, warns (among other things):
6502dis.c:21:5: Variable exported but not used outside 6502dis:
address
...
6502dis.c:33:5: Function exported but not used outside 6502dis:
getbyte
...
and so on. My question is, should I care about these warnings? Or,
better yet, how do I fix them? (The "other things" it complains
about is unistd.h, getopt.)
Second, regarding style. Is my error checking ok? Have I done any stupid
newbie things?
Anyway, I'd be very thankful for any critisism.
/* A simple 6502 disassembler
*/
/*
* Includes
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#define VERSION "0.1"
/*
* Global variables
*/
extern char *optarg;
extern int optind, opterr;
int address;
int ld;
char *filename;
/*
* typedefs
*/
typedef unsigned short int usint;
/*
* Mnemonics
*/
static const char *ASM[] = {
"BRK", "ORA", "???", "???", "???", "ORA", "ASL", "???",
"PHP", "ORA", "ASL", "???", "???", "ORA", "ASL", "???",
"BPL", "ORA", "???", "???", "???", "ORA", "ASL", "???",
"CLC", "ORA", "???", "???", "???", "ORA", "ASL", "???",
"JSR", "AND", "???", "???", "BIT", "AND", "ROL", "???",
"PLP", "AND", "ROL", "???", "BIT", "AND", "ROL", "???",
"BMI", "AND", "???", "???", "???", "AND", "ROL", "???",
"SEC", "AND", "???", "???", "???", "AND", "ROL", "???",
"RTI", "EOR", "???", "???", "???", "EOR", "LSR", "???",
"PHA", "EOR", "LSR", "???", "JMP", "EOR", "LSR", "???",
"BVC", "EOR", "???", "???", "???", "EOR", "LSR", "???",
"CLI", "EOR", "???", "???", "???", "EOR", "???", "???",
"RTS", "ADC", "???", "???", "???", "ADC", "ROR", "???",
"PLA", "ADC", "ROR", "???", "JMP", "ADC", "ROR", "???",
"BVS", "ADC", "???", "???", "???", "ADC", "ROR", "???",
"SEI", "ADC", "???", "???", "???", "ADC", "ROR", "???",
"???", "STA", "???", "???", "STY", "STA", "STX", "???",
"DEY", "???", "TXA", "???", "STY", "STA", "STX", "???",
"BCC", "STA", "???", "???", "STY", "STA", "???", "???",
"TYA", "STA", "TXS", "???", "???", "STA", "???", "???",
"LDY", "LDA", "LDX", "???", "LDY", "LDA", "LDX", "???",
"TAY", "LDA", "TAX", "???", "LDY", "LDA", "LDX", "???",
"BCS", "LDA", "???", "???", "LDY", "LDA", "LDX", "???",
"CLV", "LDA", "TSX", "???", "LDY", "LDA", "LDX", "???",
"CPY", "CMP", "???", "???", "CPY", "CMP", "DEC", "???",
"INY", "CMP", "DEX", "???", "CPY", "CMP", "DEC", "???",
"BNE", "CMP", "???", "???", "???", "CMP", "DEC", "???",
"CLD", "CMP", "???", "???", "???", "CMP", "DEC", "???",
"CPX", "SBC", "???", "???", "CPX", "SBC", "INC", "???",
"INX", "SBC", "NOP", "???", "CPX", "SBC", "INC", "???",
"BEQ", "SBC", "???", "???", "???", "SBC", "INC", "???",
"SED", "SBC", "???", "???", "???", "SBC", "INC", "???"
};
/*
* Size of mnemonics
*/
static const usint ASMSIZE[256] = {
1, 2, 1, 1, 1, 2, 2, 1,
1, 2, 1, 1, 1, 3, 3, 1,
2, 2, 1, 1, 1, 2, 2, 1,
1, 3, 1, 1, 1, 3, 3, 1,
3, 2, 1, 1, 2, 2, 2, 1,
1, 2, 1, 1, 3, 3, 3, 1,
2, 2, 1, 1, 1, 2, 2, 1,
1, 3, 1, 1, 1, 3, 3, 1,
1, 2, 1, 1, 1, 2, 3, 1,
1, 2, 1, 1, 3, 3, 3, 1,
2, 2, 1, 1, 1, 2, 2, 1,
1, 3, 1, 1, 1, 3, 1, 1,
1, 2, 1, 1, 1, 2, 2, 1,
1, 2, 1, 1, 3, 3, 3, 1,
2, 2, 1, 1, 1, 2, 2, 1,
1, 3, 1, 1, 1, 3, 3, 1,
1, 2, 1, 1, 2, 2, 2, 1,
1, 1, 1, 1, 3, 3, 3, 1,
2, 2, 1, 1, 2, 2, 1, 1,
1, 3, 1, 1, 1, 3, 1, 1,
2, 2, 2, 1, 2, 2, 2, 1,
1, 2, 1, 1, 3, 3, 3, 1,
2, 2, 1, 1, 2, 2, 2, 1,
1, 3, 1, 1, 3, 3, 3, 1,
2, 2, 1, 1, 2, 2, 2, 1,
1, 2, 1, 1, 3, 3, 3, 1,
2, 2, 1, 1, 1, 2, 2, 1,
1, 3, 1, 1, 1, 3, 3, 1,
2, 2, 1, 1, 2, 2, 2, 1,
1, 2, 1, 1, 3, 3, 3, 1,
2, 2, 1, 1, 1, 2, 2, 1,
1, 3, 1, 1, 1, 3, 3, 1
};
/* Kind of mnemonic
* 1: #$nn
* 2: $nnnn
* 3: $nnnn,x
* 4: $nnnn,y
* 5: $nn
* 6: ($nn,x)
* 7: ($nn),y
* 8: $nn,x
* 9: ($nnnn)
* 10: $nn,y
* 11: branches
*/
static const usint ASMMODE[256] = {
0, 6, 0, 0, 0, 5, 5, 0,
0, 1, 0, 0, 0, 2, 2, 0,
11,7, 0, 0, 0, 8, 8, 0,
0, 4, 0, 0, 0, 3, 3, 0,
2, 6, 0, 0, 5, 5, 5, 0,
0, 1, 0, 0, 2, 2, 2, 0,
11,7, 0, 0, 0, 8, 8, 0,
0, 4, 0, 0, 0, 3, 3, 0,
0, 6, 0, 0, 0, 5, 3, 0,
0, 1, 0, 0, 2, 2, 2, 0,
11,7, 0, 0, 0, 8, 8, 0,
0, 4, 0, 0, 0, 3, 0, 0,
0, 6, 0, 0, 0, 5, 5, 0,
0, 1, 0, 0, 9, 2, 2, 0,
11,7, 0, 0, 0, 8, 8, 0,
0, 4, 0, 0, 0, 3, 3, 0,
0, 6, 0, 0, 5, 5, 5, 0,
0, 0, 0, 0, 2, 2, 2, 0,
11,7, 0, 0, 8, 8, 0, 0,
0, 4, 0, 0, 0, 3, 0, 0,
1, 6, 1, 0, 5, 5, 5, 0,
0, 1, 0, 0, 2, 2, 2, 0,
11,7, 0, 0, 8, 8, 10,0,
0, 4, 0, 0, 3, 3, 4, 0,
1, 6, 0, 0, 5, 5, 5, 0,
0, 1, 0, 0, 2, 2, 2, 0,
11,7, 0, 0, 0, 8, 8, 0,
0, 4, 0, 0, 0, 3, 3, 0,
1, 6, 0, 0, 5, 5, 5, 0,
0, 1, 0, 0, 2, 2, 2, 0,
11,7, 0, 0, 0, 8, 8, 0,
0, 4, 0, 0, 0, 3, 3, 0
};
/*
* Get options
*/
void parse_options(int argc, char **argv)
{
int optchar;
while ((optchar = getopt(argc, argv, "a:h")) >= 0) {
switch (optchar) {
case 'a':
address = atoi(optarg);
ld = 1;
break;
case 'h':
(void) fputs("6502dis " VERSION " (" __DATE__ ")\n", stderr);
(void) fputs("Usage: 6502dis [options] inputfile\n"
"Options are:\n"
" -a addr decimal loading address\n"
" -h this help text\n", stderr);
exit(EXIT_SUCCESS);
default:
exit(EXIT_FAILURE);
}
}
if (!(filename = argv[optind])) {
(void) fputs("Error: no input file\n", stderr);
exit(EXIT_FAILURE);
}
return;
}
/*
* Get a byte from file
*/
int getbyte(FILE * fsource)
{
int opc;
if ((opc = fgetc(fsource)) == EOF) {
printf("EOF\n");
(void) fclose(fsource);
exit(EXIT_SUCCESS);
}
return (opc);
}
/*
* main
*/
int main(int argc, char **argv)
{
FILE *fsource;
int adr, adr_low, adr_high, opcode = 0, low = 0, high = 0;
usint size, mode;
address = 0;
ld = 0;
parse_options(argc, argv);
if (!(fsource = fopen(filename, "rb"))) {
fprintf(stderr, "Error: could not open: %s\n", filename);
exit(EXIT_FAILURE);
}
if (ld == 0) {
adr_low = getbyte(fsource);
adr_high = getbyte(fsource);
address = (adr_high * 256) + adr_low;
}
printf("Filename: %s\n", filename);
printf("Loading address: %d ($%04X)\n\n", address, (usint) address);
while (opcode > -1) {
opcode = getbyte(fsource);
printf("$%04X ", (usint) address);
size = ASMSIZE[opcode];
switch (size) {
case 2:
low = getbyte(fsource);
address++;
address++;
printf("%02X %02X ", (usint) opcode, (usint) low);
break;
case 3:
low = getbyte(fsource);
high = getbyte(fsource);
address++;
address++;
address++;
printf("%02X %02X %02X ", (usint) opcode, (usint) low,
(usint) high);
break;
default:
address++;
printf("%02x ", (usint) opcode);
break;
}
printf("%s ", ASM[opcode]);
mode = ASMMODE[opcode];
switch (mode) {
case 1:
printf("#$%02X", (usint) low);
break;
case 2:
printf("$%02X%02X", (usint) high, (usint) low);
break;
case 3:
printf("$%02X%02X,X", (usint) high, (usint) low);
break;
case 4:
printf("$%02X%02X,Y", (usint) high, (usint) low);
break;
case 5:
printf("$%02X", (usint) low);
break;
case 6:
printf("($%02X,X)", (usint) low);
break;
case 7:
printf("($%02X),Y", (usint) low);
break;
case 8:
printf("$%02X,X", (usint) low);
break;
case 9:
printf("($%02X%02X)", (usint) high, (usint) low);
break;
case 10:
printf("$%02X,Y", (usint) low);
break;
case 11:
if (low <= 127)
adr = address + low;
else
adr = address - (256 - low);
printf("$%04X", (usint) adr);
break;
default:
break;
}
printf("\n");
}
(void) fclose(fsource);
exit(EXIT_SUCCESS);
}
Best regards,
Peter Karlsson
My job description recently changed to include C coding, so I've got
to speed learn C. Anyway, I would be grateful for comments of
this little exercise I hacked up.
First, Splint 3.1.1 --- 13 Oct 2004, warns (among other things):
6502dis.c:21:5: Variable exported but not used outside 6502dis:
address
...
6502dis.c:33:5: Function exported but not used outside 6502dis:
getbyte
...
and so on. My question is, should I care about these warnings? Or,
better yet, how do I fix them? (The "other things" it complains
about is unistd.h, getopt.)
Second, regarding style. Is my error checking ok? Have I done any stupid
newbie things?
Anyway, I'd be very thankful for any critisism.
/* A simple 6502 disassembler
*/
/*
* Includes
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#define VERSION "0.1"
/*
* Global variables
*/
extern char *optarg;
extern int optind, opterr;
int address;
int ld;
char *filename;
/*
* typedefs
*/
typedef unsigned short int usint;
/*
* Mnemonics
*/
static const char *ASM[] = {
"BRK", "ORA", "???", "???", "???", "ORA", "ASL", "???",
"PHP", "ORA", "ASL", "???", "???", "ORA", "ASL", "???",
"BPL", "ORA", "???", "???", "???", "ORA", "ASL", "???",
"CLC", "ORA", "???", "???", "???", "ORA", "ASL", "???",
"JSR", "AND", "???", "???", "BIT", "AND", "ROL", "???",
"PLP", "AND", "ROL", "???", "BIT", "AND", "ROL", "???",
"BMI", "AND", "???", "???", "???", "AND", "ROL", "???",
"SEC", "AND", "???", "???", "???", "AND", "ROL", "???",
"RTI", "EOR", "???", "???", "???", "EOR", "LSR", "???",
"PHA", "EOR", "LSR", "???", "JMP", "EOR", "LSR", "???",
"BVC", "EOR", "???", "???", "???", "EOR", "LSR", "???",
"CLI", "EOR", "???", "???", "???", "EOR", "???", "???",
"RTS", "ADC", "???", "???", "???", "ADC", "ROR", "???",
"PLA", "ADC", "ROR", "???", "JMP", "ADC", "ROR", "???",
"BVS", "ADC", "???", "???", "???", "ADC", "ROR", "???",
"SEI", "ADC", "???", "???", "???", "ADC", "ROR", "???",
"???", "STA", "???", "???", "STY", "STA", "STX", "???",
"DEY", "???", "TXA", "???", "STY", "STA", "STX", "???",
"BCC", "STA", "???", "???", "STY", "STA", "???", "???",
"TYA", "STA", "TXS", "???", "???", "STA", "???", "???",
"LDY", "LDA", "LDX", "???", "LDY", "LDA", "LDX", "???",
"TAY", "LDA", "TAX", "???", "LDY", "LDA", "LDX", "???",
"BCS", "LDA", "???", "???", "LDY", "LDA", "LDX", "???",
"CLV", "LDA", "TSX", "???", "LDY", "LDA", "LDX", "???",
"CPY", "CMP", "???", "???", "CPY", "CMP", "DEC", "???",
"INY", "CMP", "DEX", "???", "CPY", "CMP", "DEC", "???",
"BNE", "CMP", "???", "???", "???", "CMP", "DEC", "???",
"CLD", "CMP", "???", "???", "???", "CMP", "DEC", "???",
"CPX", "SBC", "???", "???", "CPX", "SBC", "INC", "???",
"INX", "SBC", "NOP", "???", "CPX", "SBC", "INC", "???",
"BEQ", "SBC", "???", "???", "???", "SBC", "INC", "???",
"SED", "SBC", "???", "???", "???", "SBC", "INC", "???"
};
/*
* Size of mnemonics
*/
static const usint ASMSIZE[256] = {
1, 2, 1, 1, 1, 2, 2, 1,
1, 2, 1, 1, 1, 3, 3, 1,
2, 2, 1, 1, 1, 2, 2, 1,
1, 3, 1, 1, 1, 3, 3, 1,
3, 2, 1, 1, 2, 2, 2, 1,
1, 2, 1, 1, 3, 3, 3, 1,
2, 2, 1, 1, 1, 2, 2, 1,
1, 3, 1, 1, 1, 3, 3, 1,
1, 2, 1, 1, 1, 2, 3, 1,
1, 2, 1, 1, 3, 3, 3, 1,
2, 2, 1, 1, 1, 2, 2, 1,
1, 3, 1, 1, 1, 3, 1, 1,
1, 2, 1, 1, 1, 2, 2, 1,
1, 2, 1, 1, 3, 3, 3, 1,
2, 2, 1, 1, 1, 2, 2, 1,
1, 3, 1, 1, 1, 3, 3, 1,
1, 2, 1, 1, 2, 2, 2, 1,
1, 1, 1, 1, 3, 3, 3, 1,
2, 2, 1, 1, 2, 2, 1, 1,
1, 3, 1, 1, 1, 3, 1, 1,
2, 2, 2, 1, 2, 2, 2, 1,
1, 2, 1, 1, 3, 3, 3, 1,
2, 2, 1, 1, 2, 2, 2, 1,
1, 3, 1, 1, 3, 3, 3, 1,
2, 2, 1, 1, 2, 2, 2, 1,
1, 2, 1, 1, 3, 3, 3, 1,
2, 2, 1, 1, 1, 2, 2, 1,
1, 3, 1, 1, 1, 3, 3, 1,
2, 2, 1, 1, 2, 2, 2, 1,
1, 2, 1, 1, 3, 3, 3, 1,
2, 2, 1, 1, 1, 2, 2, 1,
1, 3, 1, 1, 1, 3, 3, 1
};
/* Kind of mnemonic
* 1: #$nn
* 2: $nnnn
* 3: $nnnn,x
* 4: $nnnn,y
* 5: $nn
* 6: ($nn,x)
* 7: ($nn),y
* 8: $nn,x
* 9: ($nnnn)
* 10: $nn,y
* 11: branches
*/
static const usint ASMMODE[256] = {
0, 6, 0, 0, 0, 5, 5, 0,
0, 1, 0, 0, 0, 2, 2, 0,
11,7, 0, 0, 0, 8, 8, 0,
0, 4, 0, 0, 0, 3, 3, 0,
2, 6, 0, 0, 5, 5, 5, 0,
0, 1, 0, 0, 2, 2, 2, 0,
11,7, 0, 0, 0, 8, 8, 0,
0, 4, 0, 0, 0, 3, 3, 0,
0, 6, 0, 0, 0, 5, 3, 0,
0, 1, 0, 0, 2, 2, 2, 0,
11,7, 0, 0, 0, 8, 8, 0,
0, 4, 0, 0, 0, 3, 0, 0,
0, 6, 0, 0, 0, 5, 5, 0,
0, 1, 0, 0, 9, 2, 2, 0,
11,7, 0, 0, 0, 8, 8, 0,
0, 4, 0, 0, 0, 3, 3, 0,
0, 6, 0, 0, 5, 5, 5, 0,
0, 0, 0, 0, 2, 2, 2, 0,
11,7, 0, 0, 8, 8, 0, 0,
0, 4, 0, 0, 0, 3, 0, 0,
1, 6, 1, 0, 5, 5, 5, 0,
0, 1, 0, 0, 2, 2, 2, 0,
11,7, 0, 0, 8, 8, 10,0,
0, 4, 0, 0, 3, 3, 4, 0,
1, 6, 0, 0, 5, 5, 5, 0,
0, 1, 0, 0, 2, 2, 2, 0,
11,7, 0, 0, 0, 8, 8, 0,
0, 4, 0, 0, 0, 3, 3, 0,
1, 6, 0, 0, 5, 5, 5, 0,
0, 1, 0, 0, 2, 2, 2, 0,
11,7, 0, 0, 0, 8, 8, 0,
0, 4, 0, 0, 0, 3, 3, 0
};
/*
* Get options
*/
void parse_options(int argc, char **argv)
{
int optchar;
while ((optchar = getopt(argc, argv, "a:h")) >= 0) {
switch (optchar) {
case 'a':
address = atoi(optarg);
ld = 1;
break;
case 'h':
(void) fputs("6502dis " VERSION " (" __DATE__ ")\n", stderr);
(void) fputs("Usage: 6502dis [options] inputfile\n"
"Options are:\n"
" -a addr decimal loading address\n"
" -h this help text\n", stderr);
exit(EXIT_SUCCESS);
default:
exit(EXIT_FAILURE);
}
}
if (!(filename = argv[optind])) {
(void) fputs("Error: no input file\n", stderr);
exit(EXIT_FAILURE);
}
return;
}
/*
* Get a byte from file
*/
int getbyte(FILE * fsource)
{
int opc;
if ((opc = fgetc(fsource)) == EOF) {
printf("EOF\n");
(void) fclose(fsource);
exit(EXIT_SUCCESS);
}
return (opc);
}
/*
* main
*/
int main(int argc, char **argv)
{
FILE *fsource;
int adr, adr_low, adr_high, opcode = 0, low = 0, high = 0;
usint size, mode;
address = 0;
ld = 0;
parse_options(argc, argv);
if (!(fsource = fopen(filename, "rb"))) {
fprintf(stderr, "Error: could not open: %s\n", filename);
exit(EXIT_FAILURE);
}
if (ld == 0) {
adr_low = getbyte(fsource);
adr_high = getbyte(fsource);
address = (adr_high * 256) + adr_low;
}
printf("Filename: %s\n", filename);
printf("Loading address: %d ($%04X)\n\n", address, (usint) address);
while (opcode > -1) {
opcode = getbyte(fsource);
printf("$%04X ", (usint) address);
size = ASMSIZE[opcode];
switch (size) {
case 2:
low = getbyte(fsource);
address++;
address++;
printf("%02X %02X ", (usint) opcode, (usint) low);
break;
case 3:
low = getbyte(fsource);
high = getbyte(fsource);
address++;
address++;
address++;
printf("%02X %02X %02X ", (usint) opcode, (usint) low,
(usint) high);
break;
default:
address++;
printf("%02x ", (usint) opcode);
break;
}
printf("%s ", ASM[opcode]);
mode = ASMMODE[opcode];
switch (mode) {
case 1:
printf("#$%02X", (usint) low);
break;
case 2:
printf("$%02X%02X", (usint) high, (usint) low);
break;
case 3:
printf("$%02X%02X,X", (usint) high, (usint) low);
break;
case 4:
printf("$%02X%02X,Y", (usint) high, (usint) low);
break;
case 5:
printf("$%02X", (usint) low);
break;
case 6:
printf("($%02X,X)", (usint) low);
break;
case 7:
printf("($%02X),Y", (usint) low);
break;
case 8:
printf("$%02X,X", (usint) low);
break;
case 9:
printf("($%02X%02X)", (usint) high, (usint) low);
break;
case 10:
printf("$%02X,Y", (usint) low);
break;
case 11:
if (low <= 127)
adr = address + low;
else
adr = address - (256 - low);
printf("$%04X", (usint) adr);
break;
default:
break;
}
printf("\n");
}
(void) fclose(fsource);
exit(EXIT_SUCCESS);
}
Best regards,
Peter Karlsson