📄 pcasm5b.c
字号:
/*
**
** PCASM
** Assembler for the PC (PopCorn) 8 bit CISC processor
**
**
** 1/23/99
** o added command line interfacing
**
** 1/19/99
** o added ability to tell in which line unresolved labels occurs
** o had the output file be dumped to a file
**
** 1/18/99
** o a whole lot of things works now. See 'rules.dat'
** o fixed a bug in reg_find() routine. It used to get stuck in infite
** loop if no valid register mnemonic is found
** o added error list
**
** 1/11/99
** Started work on the assembler
**
*/
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <math.h>
#define BUFFSIZE 512
#define CODESIZE 4096
#define LABEL_SIZE 2048
#define BL 25 // length of line buffer
#define NL '\n'
#define CR '\r'
#define TAB '\t'
#define FORMFEED '\f'
#define MODE_BYTE 0
#define MODE_ADDX 1
#define LINE_BUFF_SIZE 100
#define ERROR_LIST_SIZE 100
#define debug
#define debug2 0
#define filedebug
main (int argc, char *argv[])
//main ()
{
// Vars and etc
FILE *fp, *fopen(), *fp_opcode, *exec_file, *list_fp;
int fclose(),c,tt;
unsigned char *c_buffer,d,*file_name, *c_code, *binary_name, *list_file;
unsigned char *str_label1, *line_lab;
unsigned int result_buffer[BL];
int source_line_count,i,j,c_code_ptr,k;
int mnemonic_line_count;
int line_start,line_end;
char line_buff[LINE_BUFF_SIZE],ca,cb,cc,cd,ce,cf;
char mnemonic[7],mychar;
int value,qq,x,y,z,word_len,word_len2,ptr,ptr2,match;
int label_addx;
unsigned int label_index1[100], line_lab_index[100];
unsigned int label_line[100];
unsigned int str_label1_ptr, str_label2_ptr, line_lab_ptr;
unsigned int label_index1_ptr, line_lab_index_ptr;
unsigned int error_counter, labels_matched;
unsigned char nextlabel[BL], nextlabel2[BL];
unsigned int error_list[ERROR_LIST_SIZE];
// Prototype declaration
unsigned int count_line();
void find_mnemonic();
void find_immed();
int find_word();
int find_reg();
/*
printf("argument count =%d\n",argc);
for(i=0;i<argc;i++)
{ myargv[i] = argv[i];
printf("Arguments = %s\n",myargv[i]);
}
*/
file_name = "xx.asm";
//binary_name = "out.bin";
//list_file = "out.lst";
// a note about the error list
// the even location 0,2,4, ... contains the source line
// where the error is
// the odd locations 1,3,5, ... contains the error code
//
// error code:
// 00 = unresolved label
//
// A word about labels
// there are two labels:
// - opcode label, which is the address in the branching opcode in
// text form
// - line libel, which is the 'word' a line of code starts with
//
// During pass 1, both of these labels are stored, literally, along
// with the address where they are located. There are 5 arrays
// associated with this:
//
// unsigned char str_label1[]
// this array holds the literal characters making up the label
// found in an instruction. It is space (0x20) terminated
//
// unsigned int label_index1[]
// this array holds the address where the label in str_label1[] was
// found. The indexes of this array and the str_label1 array are
// the same
//
// unsigned int label_line[]
// this array holds the line in which the opcode label was found.
// it is used for error purposes
//
//
// unsigned char line_lab[]
// this array holds the literal characters making up the line label
// it is space ' ' terminated
//
// unsigned int line_lab_index[]
// array holding the address of the opcode following this label
//
//
// During pass2, the two arrays are compared to resolve the addresses
//
//
label_index1_ptr = 0;
line_lab_ptr = 0;
str_label1_ptr = 0;
line_lab_index_ptr = 0;
error_counter = 0;
/* open the source file .. to be replaced by command argument */
/* if( (fp=fopen(file_name,"r+")) == NULL )
{ printf("error opening file\n");
exit(-1);
}
*/
if(argc<4) {
printf("Usage\n");
printf("pcasm [sourcefile] [binaryfile] [listfile]\n");
printf("where:\n");
printf("sourcefile = the assembler code file\n");
printf("binaryfile = compiled file name\n");
printf("listfile = debug listing file name\n");
exit(-1);
}
if( (fp=fopen(argv[1],"r+")) == NULL )
{ printf("error opening file\n");
exit(-1);
}
// Open the listing file
if( (list_fp=fopen(argv[3],"w")) == NULL )
{ printf("error opening list file\n");
exit(-1);
}
source_line_count = count_line(fp);
fprintf(list_fp,"\nSource File: \t%s\n",argv[1]);
fprintf(list_fp,"Dest File: \t%s\n",argv[2]);
fprintf(list_fp,"Listing File: \t%s\n",argv[3]);
fprintf(list_fp,"\nTotal line count in source file= %d\n",source_line_count);
/* open the opcode definition file */
if( (fp_opcode=fopen("opcode.dat","r+")) == NULL )
{ printf("error opening 'opcode.dat'\n");
exit(-1);
}
mnemonic_line_count = count_line(fp_opcode);
fprintf(list_fp,"Total line count in opcode.dat= %d\n",mnemonic_line_count);
// dump file for debug
#if(debug2)
c=10;
while( c!=EOF)
{ c=fgetc(fp);
if (c==TAB)
printf(".TAB.");
else if(c==NL)
printf("..NL\n");
else
printf("%c",c);
}
rewind(fp);
// dump opcode.dat
for(j=0;j<mnemonic_line_count;j++)
{ fscanf(fp_opcode,"%s %x",mnemonic,&value);
fprintf(list_fp,"%s %x\n",mnemonic,value);
}
#endif
//
// Request memory space for buffer (type char)
//
if ( (c_buffer=(unsigned char *)malloc(BUFFSIZE)) == NULL)
{ printf("error reserving memory space\n");
exit(-1);
}
//
// Request 4Kb of memory space to hold the compiled code
//
if ( (c_code=(unsigned char*)malloc(CODESIZE)) == NULL )
{ printf("could not reserve 4Kb of code space\n");
exit(-2);
}
//
// Request 4Kb of memory space to hold labels on Pass 1
//
if ( (str_label1=(unsigned char*)malloc(LABEL_SIZE)) == NULL )
{ printf("could not reserve 4Kb of label pass 1 space\n");
exit(-3);
}
//
// Request 4Kb of memory space to hold labels on Pass 2
//
if ( (line_lab=(unsigned char*)malloc(LABEL_SIZE)) == NULL )
{ printf("could not reserve 4Kb of label pass 2 space\n");
exit(-4);
}
//
// Pass 1:
// Go through the code "line-by-line" e.i. between CR's and
// scan for valid opcode, translate it and write the opcode byte(s)
// into the c_code buffer.
//
rewind(fp); // reset source file pointer to beginning
line_end = -1; // initial value of line_end
c_code_ptr=0;
for (i=0;i<source_line_count;i++)
{
//flush line buffer
for(j=0;j<LINE_BUFF_SIZE;j++) line_buff[j]=NULL;
// mark the beginning of present line. I.E. loc of last NL + 1
line_start = line_end+1;
// find end of present line. I.E. where NL is found
// and copy the line into a buffer
j=0;
while( (c=fgetc(fp)) != NL )
{ line_buff[j]=c; // copy chars into line buffer
j++;
}
line_end = line_start + j;
line_buff[j]==NULL; // stuff null to end of line buffer
fprintf(list_fp,"line %d %s\n",i,line_buff); // print source line
fprintf(list_fp,"\t");
// find opcode in the present line
find_mnemonic(fp_opcode,line_buff,j,mnemonic_line_count,&result_buffer,list_fp);
// if there is an error, record it in error_list[]
if((result_buffer[0]&0x0f)==2)
{ error_list[2*error_counter] = i+1;
error_list[2*error_counter+1] = result_buffer[0];
error_counter++;
}
// if a valid opcode was found , update c_code buffer
if ( (result_buffer[0]&(0x7f))==0 || (result_buffer[0]&(0x7f))==3 )
{ fprintf(list_fp,"\t%X: ",c_code_ptr);
for(qq=0;qq<result_buffer[1];qq++) {
c_code[c_code_ptr+qq]=result_buffer[qq+2];
fprintf(list_fp,"%X ",c_code[c_code_ptr+qq]);
}
c_code_ptr=c_code_ptr+qq;
fprintf(list_fp,"\n");
}
else
fprintf(list_fp,"\n");
// if a label was found within the instruction..
if( (result_buffer[0]&(0x7f)) == 3)
{ x=result_buffer[1]+2;
y=result_buffer[x];
for(tt=0;tt<y;tt++)
{ mychar=result_buffer[x+tt+1];
*(str_label1+str_label1_ptr)=mychar;
str_label1_ptr++;
}
*(str_label1+str_label1_ptr)=' '; // insert a blank at the end
str_label1_ptr++;
// save the addx of this label
label_index1[label_index1_ptr]=c_code_ptr-result_buffer[1]+1;
// save the line where this label occurred
label_line[label_index1_ptr] = i+1;
label_index1_ptr++; // point to next label
}
// if a line starts with a label ..
if( (result_buffer[0]&(0x80)) != 0 )
{ ptr=0; // we're still in the same line, so get the first word
word_len=find_word(line_buff,&ptr,BL,nextlabel2);
// copy the label into the str_label2 buffer
for(tt=0;tt<(word_len-1);tt++)
{ mychar = *(nextlabel2+tt);
*(line_lab+line_lab_ptr) = mychar;
line_lab_ptr++;
}
*(line_lab+line_lab_ptr)=' '; // insert a blank at the end
line_lab_ptr++;
// if the line has label and opcode, mark the addx of the opcode
// as the address of label
if( ( (result_buffer[0]&(0x8F)) == 0x80 ) || \
( (result_buffer[0]&(0x8F)) == 0x83 ) )
{ line_lab_index[line_lab_index_ptr]=c_code_ptr-result_buffer[1];
line_lab_index_ptr++;
}
// else if this line only has label, mark present c_code_ptr + 1
// as the address of the label
else if( (result_buffer[0]&(0x8F)) == 0x81 )
{ line_lab_index[line_lab_index_ptr]=c_code_ptr ;
line_lab_index_ptr++;
}
}
} // pass 1
/*
** PASS 2
**
** Resolve labels from the two label arrays:
** str_label1 array which hold the literal label names from
** opcodes
** line_lab array which holds the literal label names from
** line beginning
**
** Store the line# of the unresolved label in the error_table
**
*/
// scan through howmany opcode labels there are
ptr=0;
match=1;
labels_matched=0;
for(i=0;i<label_index1_ptr;i++)
{
// get opcode label
word_len = find_word(str_label1,&ptr,LABEL_SIZE,nextlabel);
ptr2=0;
for (j=0;j<line_lab_index_ptr;j++)
{
word_len2 = find_word(line_lab,&ptr2,LABEL_SIZE,nextlabel2);
if((match=strcmp(nextlabel,nextlabel2))==0)
break; // break out of this loop if match is found
}
// in the event match is found..
if(match==0)
{ label_addx = line_lab_index[j]; // get line label addx
c_code[label_index1[i]] = label_addx%256;
c_code[label_index1[i]+1]= label_addx/256;
labels_matched++;
}
// if no match is found, store this line number in the error_list
// array. the error code for unresolved label is 0
else
{
error_list[error_counter*2] = label_line[i];
error_list[error_counter*2+1] = 0;
error_counter++;
}
} // pass2
/*
** SAVE RESULT
*/
/* open the opcode definition file */
if( (exec_file=fopen(argv[2],"w")) == NULL )
{ fprintf(list_fp,"error opening opcode.bin\n");
exit(-1);
}
for(i=0;i<CODESIZE;i++)
{ fprintf(exec_file,"%X ",c_code[i]);
if( (i%8) == 0 )
fprintf(exec_file,"\n");
}
fclose(exec_file);
// Print error list
tt=label_index1_ptr-labels_matched;
fprintf(list_fp,"\nTotal Errors = %d \n",error_counter+tt);
i=0;
while(i!=error_counter)
{
j=error_list[2*i];
k=error_list[2*i+1];
fprintf(list_fp,"error in line %d : ",j);
if(k==0)
fprintf(list_fp," unresolved label\n");
else
fprintf(list_fp," code %d\n",k);
i++;
}
if (labels_matched==label_index1_ptr)
fprintf(list_fp,"All labels resolved\n");
else
fprintf(list_fp,"Error: there are %d label(s) unresolved\n",tt);
// opcode label table
ptr=0;
fprintf(list_fp,"\nOpcode Label Table\n");
fprintf(list_fp,"==================\n");
fprintf(list_fp,"addx \t label\n\n");
for(i=0;i<label_index1_ptr;i++)
{ word_len=find_word(str_label1,&ptr,LABEL_SIZE,nextlabel);
fprintf(list_fp,"%d \t %s\n",label_index1[i],nextlabel);
}
// pass 1 :: line label table
ptr=0;
fprintf(list_fp,"\nLine Label Table\n");
fprintf(list_fp,"==================\n");
fprintf(list_fp,"addx \t label\n\n");
for(i=0;i<line_lab_index_ptr;i++)
{ word_len=find_word(line_lab,&ptr,LABEL_SIZE,nextlabel);
fprintf(list_fp,"%d \t %s\n",line_lab_index[i],nextlabel);
}
// Raw hex dump of data
for(i=0;i<50;i++)
{ if(i%10==0)
fprintf(list_fp,"\n");
fprintf(list_fp,"%x ",c_code[i]);
}
// free-up all allocated memory and close all opened files
free(c_buffer);
free(c_code);
free(str_label1);
free(line_lab);
fclose(fp);
fclose(fp_opcode);
fclose(list_fp);
}
/*
** Determine the number of lines
**
** This subroutine DESTROYS the current location of file pointer
** and resets it to the beginning of the file
*/
unsigned int count_line(FILE *fp)
{
unsigned int line_count=0;
unsigned int c;
while((c=fgetc(fp))!=EOF)
if (c==NL)
line_count++;
rewind(fp);
return(line_count);
}
/*
** find_mnemonic
**
**
** input:
** unsigned char *line_buffer pointer to line_buffer
** unsigned int length length of line_buffer
** FILE *fp_opcode file pointer to opcode.dat
** unsigned int mnemonic_lines total lines in mnemonic file
** unsigned int *result_buffer pointer to result buffer
**
**
** outputs:
** unsigned int result_buffer[]
** contains the following data:
** result_buffer[0] status:
** msb=1 the line starts with a label
** 3 a branching opcode with label was found
** 2 means error, opcode found, but
** 1 means no opcode found
** 0 means opcode found, and all is ok
** result_buffer[1]
** number of opcodes
** result_buffer[2 ~ N]
** opcodes making up the instruction
** result_buffer[N+1]
** the length of the label
** result_buffer[N+2 ~ M]
** label iff result_buffer[0]==3
** N=length of opcode
** M=length of label
**
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -