⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcasm5b.c

📁 这是8位微处理器的Verilog源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
**
**  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 + -