如何让这个C程序“挂”?

时间:2012-03-19 17:03:35

标签: c assembly

我正在尝试使用我编写的C程序读取SIC / XE程序中的行(它应该像传递SICASM汇编程序一样)。但是,如果最后一行SIC / XE代码在mneumonic之后没有操作数,程序将“挂起”(不会完成执行)。我想摆脱悬挂,组装将从那里开始。

以下是获得输入的程序:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>

#define SIZE 51
#define LABEL_SIZE 9
#define MNEUMONIC_SIZE 8
#define OPERAND_SIZE 10

void getData(FILE* fpIn);
int hashFunc(char label[]);
unsigned long hex2int(char *a, unsigned int len);
bool checkMneumonic(char* mneumonic, int* bytes);

int main(int argc, char* argv[])
{
   FILE* fpIn = fopen(argv[1], "r");   
   if(fpIn != NULL)
      printf("\nFile open.");
   else
   {
      printf("\nError: Main needs an input file.\n");
      exit(EXIT_FAILURE);
   }

   getData(fpIn);

   fclose(fpIn);
   printf("\nFileClosed");

   printf("\n\n");
   return 0;
}

void getData(FILE* fpIn)
{
//debug printf("\nIn \"getData\" ");

   char label[LABEL_SIZE];
   char mneumonic[MNEUMONIC_SIZE];
   char operand[OPERAND_SIZE];
   int startAddr, currentAddr, PC = 0;
   bool gotValidMneu = true;
   int bytes;

   //open file for writing
   FILE* fpOut = fopen("output", "w");
   if(fpOut != NULL)
      printf("\n Ready to write.");

   fprintf(fpOut,"\n\tHash\tLabel\tAddress");

   char string1[10];
   char string2[10];
   int size;
   while( fscanf(fpIn, "%s", string1) != EOF)
   {         
      gotValidMneu = true;

      if(strcmp(string1, "LTORG") == 0)
         strcpy(string2, " ");
      else if(strcmp(string1, "RSUB") == 0)
         strcpy(string2, " ");
      else if(!feof(fpIn) && fgetc(fpIn) != '\n')
         fscanf(fpIn,"%s", string2);

      if(checkMneumonic(string1, &size) && !feof(fpIn))
      {
         strcpy(mneumonic, string1);
         strcpy(operand, string2);
         strcpy(label, " ");
      }
      else if(checkMneumonic(string2, &size) && !feof(fpIn))
      {
         strcpy(label, string1);
         strcpy(mneumonic, string2);
         fscanf(fpIn, "%s[\n]", operand);
      }
      else if( string1[0] == '.')
      {
         char junk[80];
         fgets(junk, 80, fpIn);
         gotValidMneu = false;
      }
      else
      {
         printf("\nError: got invalid mneumonic");
         gotValidMneu = false;
      }

      if(gotValidMneu)
      {
         //adjust the current address
         currentAddr = PC;

         //get the starting address
         if(strcmp(mneumonic, "START") == 0)
         {
            startAddr = hex2int(operand, strlen(operand) );
            PC = startAddr;
         }

         //mneumonic is "BASE"
         else if(strcmp(mneumonic, "BASE") == 0);

         //mneumonic is "RESW"
         else if(strcmp(mneumonic, "RESW") == 0)
         {
            PC += (3 * atoi(operand) );
         }

         //mneumonic is "BYTE"
         else if(strcmp(mneumonic, "BYTE") == 0 )
         {
            PC += atoi(operand);
         }

         //mneumonic is "END"
         else if(strcmp(mneumonic, "END") == 0);

         //check if the mneumonic is valid
         else if(checkMneumonic(mneumonic, &bytes) )
         {
            PC += bytes;
         }

         //got a bad mneumonic
         else
         {
            gotValidMneu = false;
            printf("\nError: \"%s\" is not a valid mneumonic.", mneumonic);
            fprintf(fpOut,"\nError: \"%s\" is not a valid mneumonic.", 
                    mneumonic);
         }

         if(gotValidMneu)
         {
            if(strcmp(label, " ") != 0 )
               fprintf(fpOut,"\n\t%d\t%s\t%x", hashFunc(label), label, 
                       currentAddr);
            printf("\n%x\t%s\t%s\t%s", currentAddr, label, mneumonic, operand);
         }

      }

      if(gotValidMneu)
      //flush the comments, if any
      while( '\n' != getc(fpIn) )
         getc(fpIn);

   } //end while
   fprintf(fpOut,"\n");
   fclose(fpOut);
   printf("\n Symbol table sent to file: \"output\".");
}

int hashFunc(char label[])
{
   int i, sum, hashVal;
   sum = 0;

   for(i = 0; i < strlen(label); i++)
      sum += label[i];

   hashVal = sum % SIZE;
//   printf("\nHashed Index: %d", hashVal);

   return hashVal;
}

unsigned long hex2int(char *a, unsigned int len)
{
    int i;
    unsigned long val = 0;

    for(i=0;i<len;i++)
       if(a[i] <= 57)
        val += (a[i]-48)*(1<<(4*(len-1-i)));
       else
        val += (a[i]-55)*(1<<(4*(len-1-i)));
    return val;
}

bool checkMneumonic(char mneumonic[], int* bytes)
{
   bool valid = false;
   char validMneumonic[MNEUMONIC_SIZE];

   FILE* fpIn = fopen("sicOps", "r");

   while( (fscanf(fpIn, "%s %d", validMneumonic, bytes) != EOF) )
   {
      if(strcmp(mneumonic, validMneumonic) == 0 )
      {
         valid = true;
         break;
      }
   }

   fclose(fpIn);
   return valid;
}

这是我用来测试它的文件:

ADDRES    START    100
. tests pc forward addressing
. tests base addressing
. tests pc backward addressing
NOW      +LDB     #BEGIN              load base register
XXX       BASE     BEGIN              tell assembler
YYY       LDA      BE                 A <- (m..m+2)
EN        RESW     4
BE        WORD     2
BEGIN     RESW     1
JUNK      RESW     2200
THERE     RESW     1
ZZZ       LDA      JUNK
MMM       STA      THERE
          END 

编辑:有很多新代码。我删减了原始程序,编译并测试了它并且它挂了。

3 个答案:

答案 0 :(得分:4)

您的I / O代码非常复杂(对于如此少的代码行)。

最好将整行读入缓冲区,然后分析缓冲区(在内存中),而不是试着动态决定如何构建阅读。

只需使用fgets()加载行,或getline()如果有加载行。

在回复评论时,确定你仍然需要决定如何解析这一行,但你不会冒“挂”程序等待不存在的输入。

您的行似乎由最多三个标记组成,由空格分隔,可选地后跟一个跨越行末尾的注释。要弄清楚如何把它拆分成这些碎片应该不会太难。

答案 1 :(得分:1)

使用fgets,然后使用tokenizer将字符串标记为'space'。简单的for循环中的strtok将使它变得更容易。

答案 2 :(得分:1)

我看不到你发布的代码是如何挂起的,无论是通过等待来自文件的输入还是通过循环,所以看起来实际的问题在程序的其他地方。也许与发布的片段结合使用。

但我发现你使用的是 feof ,这在C程序中几乎总是错误的,因为只有之后才会返回true 。改为使用各种输入调用的返回值。

编辑:

我实际上尝试了你的代码,添加了使它成为一个完整的,可编译的程序所需的最少代码,并在你的示例输入上尝试了它。它没有挂起。您应该总是尝试发布一个最小的工作程序 仍然会出现问题。现在你删除了似乎相关的部分。