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

📄 pl0asm.c

📁 PL0文法编译器
💻 C
📖 第 1 页 / 共 2 页
字号:
     ga(1, "dosseg");
     ga(1, ".model  small");
   }
   ga(0, ";");
   ga(1, ".stack  10240");
   ga(0, ";");
   ga(1, ".data");
   ga(0, "base    dw      0");
   ga(0, "buffer  db      80 dup (?)");
   ga(0, "blen    db      80");
   ga(0, "blank   db      ' $'");
   ga(0, "minus   db      '-$'");
   ga(0, "crlf    db      13, 10, '$'");
   ga(0, "bytecnt dw      ?");
   ga(0, "pflag   db      ?");
}

void prolog2()
{
   ga(0, ";");
   
   ga(1, ".code");
   ga(0, "start:");
   if (!os2) {
      ga(1, "mov     ax, @data");
      ga(1, "mov     ds, ax");
   }
   ga(0, ";");
   ga(1, "mov     ax, 0");
   ga(1, "push    ax");
   ga(1, "mov     [base], sp");     /* Base pointer */
   ga(1, "mov     ax, sp");
   ga(1, "push    ax");
   ga(0, ";");
}

void epilog()
{
   ga(0, ";");
   ga(0, "; Assembler epilog");
   ga(0, ";");
   ga(0, ";  Runtime Support for PL0-Compiler mit");
   ga(0, ";  Assembler-Code-Generierung");
   ga(0, ";"); 
   ga(0, "p_sbs   proc");
   ga(0, ";  Base-Adresse des DSA suchen");
   ga(0, ";   Eingabeparameter:");
   ga(0, ";   CX  Leveldifferenz");
   ga(0, ";   Ausgabeparameter:");
   ga(0, ";   DX  Resultat Base");
   ga(1, "mov     dx, [base] ");
   ga(0, "sbs2:");
   ga(1, "cmp     cx, 0");
   ga(1, "je      sbs1");
   ga(1, "mov     bp, dx");
   ga(1, "mov     dx, word ptr [bp]"); /* Alte Base */
   ga(1, "dec     cx");
   ga(1, "jmp     sbs2");
   ga(0, "sbs1:");
   ga(1, "ret  ");
   ga(0, "p_sbs   endp");
   ga(0, ";");
   ga(0, "endprocess  proc");
   if (os2) {
     ga(0, ";   Prozess durch OS/2-Funktion beenden");
     ga(1, "mov     ax, 0");
     ga(1, "push    ax   ");
     ga(1, "mov     ax, 1");
     ga(1, "push    ax   ");
     ga(0, "extrn   DosExit: far");
     ga(1, "call    far ptr DosExit");
   } else {
     ga(0, ";   Prozess durch DOS-Funktion beenden");
     ga(1, "mov     ah, 4Ch");
     ga(1, "int     21h");      /* Prozess beenden */
   }
   ga(1, "ret");
   ga(0, "endprocess  endp");
   ga(0, ";");
   ga(0, "printint  proc");
   ga(0, ";  Integer-Zahl ausgeben");
   ga(0, ";    Eingabeparameter:  ");
   ga(0, ";    AX  Zahl  ");
   ga(0, ";    CX  Laenge");
   ga(1, "mov     bx, offset buffer");  /* number2string */
   ga(1, "cmp     ax, 32767        ");  /* Zahl < 0      */
   ga(1, "jbe     prn1");
   ga(1, "neg     ax               ");  /* 2-er Kompl.   */
   ga(1, "call    number2string    ");
   ga(1, "mov     bx, offset buffer");  /* Param. f. outstring */
   ga(1, "cmp     [bx], byte ptr ' '");
   ga(1, "jne     prn5 ");
   ga(1, "inc     bx   ");
   ga(1, "mov     cx, 4");
   ga(0, "prn3:   cmp     [bx], byte ptr ' '");
   ga(1, "jne     prn4" );
   ga(1, "inc     bx");
   ga(1, "loop    prn3" );
   ga(0, "prn5:   mov     bx, offset minus");
   ga(1, "call    outstring");
   ga(1, "jmp     prn6" );
   ga(0, "prn4:   dec     bx");
   ga(1, "mov     [bx], byte ptr '-'");
   ga(1, "mov     bx, offset blank");
   ga(1, "call    outstring");
   ga(0, "prn6:   mov     bx, offset buffer");
   ga(1, "call    outstring");
   ga(1, "jmp     prn2" );
   ga(0, "prn1:   call    number2string");
   ga(1, "mov     bx, offset blank ");
   ga(1, "call    outstring        ");
   ga(1, "mov     bx, offset buffer");
   ga(1, "call    outstring        ");
   ga(0, "prn2:   mov     bx, offset blank");
   ga(1, "call    outstring        ");
   ga(1, "ret");
   ga(0, "printint  endp");
   ga(0, ";");
   ga(0, "number2string  proc");
   ga(0, ";  Umwandeln einer Dualzahl in einen String");
   ga(0, ";    Eingabeparameter:");
   ga(0, ";    AX    Zahl");
   ga(0, ";    DS:BX Zeiger auf Puffer zum Speichern d. Strings");
   ga(0, ";    CX    Anzahl der Zeichen");
   ga(1, "mov     si, 10  ");
   ga(1, "mov     di, cx  ");
   ga(1, "add     bx, cx  ");
   ga(1, "mov     [bx], byte ptr '$'");
   ga(1, "dec     bx      ");
   ga(0, "wandeln:       ");
   ga(1, "sub     dx, dx  ");
   ga(1, "div     si      ");
   ga(1, "add     dl, '0' ");
   ga(1, "mov     [bx], dl");
   ga(1, "dec     bx      ");
   ga(1, "loop    wandeln ");
   ga(1, "mov     cx, di  ");
   ga(1, "inc     bx      ");
   ga(1, "dec     cx      ");
   ga(0, "blanks:        ");
   ga(1, "cmp     [bx], byte ptr '0'");
   ga(1, "jne     fertig  ");
   ga(1, "mov     [bx], byte ptr ' '");
   ga(1, "inc     bx      ");
   ga(1, "loop    blanks  ");
   ga(0, "fertig:        ");
   ga(1, "ret            ");
   ga(0, "number2string  endp");
   ga(0, ";");
   ga(0, "outstring  proc");
   ga(0, ";  Ausgabe eines Strings unter MS-DOS oder OS/2");
   ga(0, ";    Eingabeparameter:");
   ga(0, ";    DS:BX  Zeiger auf String");
   ga(1, "mov     dx, bx");
   ga(1, "mov     cx, 0 ");
   ga(0, "anfang:");
   ga(1, "inc     cx    ");
   ga(1, "inc     bx    ");
   ga(1, "cmp     [bx], byte ptr '$'");
   ga(1, "jne     anfang");
   if (os2) {
     ga(1, "mov     bx, dx");
     ga(1, "mov     ax, 1 ");
     ga(1, "push    ax    ");      /* stdout */
     ga(1, "push    ds    ");   
     ga(1, "push    bx    ");      /* Puffer */
     ga(1, "push    cx    ");      /* Laenge */
     ga(1, "push    ds    "); 
     ga(1, "mov     dx, offset bytecnt"); 
     ga(1, "push    dx    ");      /* Rueckgabewert */ 
     ga(0, "extrn   DosWrite:far");
     ga(1, "call    far ptr DosWrite");
   } else {
     ga(1, "mov     ah, 40H ");
     ga(1, "mov     bx, 1   ");
     ga(1, "int     21h     ");
   }
   ga(1, "ret            ");
   ga(0, "outstring endp");
   ga(0, ";");
   ga(0, "string2number  proc");
   ga(0, ";  Umwandeln einer String in eine Dualzahl");
   ga(0, ";    Eingabeparameter:");
   ga(0, ";    DS:BX  Zeiger auf Puffer mit String");
   ga(0, ";    CX     Anzahl der Zeichen");
   ga(0, ";    Ausgabeparameter:");
   ga(0, ";    AX     Zahl");
   ga(1, "mov     pflag, 0 ");
   ga(1, "cmp     [bx], byte ptr '-'");
   ga(1, "jne     pos      ");
   ga(1, "mov     pflag, 1 ");
   ga(1, "inc     bx       ");
   ga(1, "dec     cx       ");
   ga(0, "pos:");
   ga(1, "mov     si, 10   ");   /* Multiplikator */
   ga(1, "sub     ax, ax   ");
   ga(0, "mult:");
   ga(1, "mul     si       ");   /* mit 10 mult.  */
   ga(1, "mov     dh, 0    ");
   ga(1, "mov     dl, [bx] ");   /* Byte anschauen */
   ga(1, "sub     dl, byte ptr '0'"); /* in Dualzahl */
   ga(1, "mov     di, dx   ");
   ga(1, "add     ax, di   ");   /* addieren */
   ga(1, "inc     bx       ");   /* n刢hstes Byte */
   ga(1, "loop    mult     ");
   ga(1, "cmp     pflag, 1 ");
   ga(1, "je      nega     ");
   ga(1, "ret");
   ga(0, "nega:   neg     ax");
   ga(1, "ret");
   ga(0, "string2number endp");
   ga(0, ";");
   ga(0, "instring  proc");
   ga(0, ";  Einlesen eines Strings vom Keyboard (MS-DOS)");
   ga(0, ";  bzw. von stdin (MS OS/2)");
   ga(0, ";    Eingabeparameter:");
   ga(0, ";    DS:BX  Zeiger auf Puffer");
   ga(0, ";    AL     L刵ge des Puffers");
   ga(0, ";    Ausgabeparameter:");
   ga(0, ";    AL     Anzahl der gelesenen Bytes");
   if (os2) { 
     ga(1, "mov     cx, 0");
     ga(1, "push    cx   ");  /* stdin */
     ga(1, "push    ds   ");
     ga(1, "push    bx   ");  /* Puffer */
     ga(1, "mov     ah, 0");
     ga(1, "push    ax   ");  /* Laenge */
     ga(1, "push    ds   "); 
     ga(1, "mov     cx, offset bytecnt");
     ga(1, "push    cx   ");  /* Rueckgabewert */ 
     ga(0, "extrn   DosRead:far");
     ga(1, "call    far ptr DosRead");
     ga(1, "mov     ax, [bytecnt]  ");
   } else {
     ga(1, "mov     ah, 3FH   ");
     ga(1, "mov     dx, bx    ");
     ga(1, "mov     bx, 0     ");
     ga(1, "mov     ch, 0     ");
     ga(1, "mov     cl, al    ");
     ga(1, "int     21h       ");
   }
   ga(1, "ret");
   ga(0, "instring endp   ");
   ga(0, ";");
   ga(1, "end      start");
}

main(argc, argv)
/*------------------------------------------------------------------
   The main function of the code generator reads the intermediate
   code file and writes the assembler output on the code file.
------------------------------------------------------------------*/
int argc;
char *argv[];
{
   int h1, h2, count, pc;
   char cname[20], aname[20];
   char *p;

   printf("PL/0-Compiler: Code generator for 80x86 assembler");

   /* check arguments */
   if (argc == 1) {
      fprintf(stderr, "\nUsage: %s pcode\n", argv[0]);
      exit(1);
   }

   for (h1=2; h1<=argc-1; h1++) {
      if (strcmp(argv[h1], "-c") == 0) comment = 1;
      if (strcmp(argv[h1], "-2") == 0) os2 = 1;
   }

   if (os2) printf(" (MS OS/2)\n");
   else printf(" (MS-DOS)\n");

   /* set up filenames */
   strcpy(cname, argv[1]);
   p = strchr(cname, '.');
   if (p) *p = 0;
   strcpy(aname, cname);
   strcat(cname, ".cod");
   strcat(aname, ".asm");

   /* open files */
   if ((intcode = fopen(cname, "r")) == NULL) {
      fprintf(stderr, "Cannot open intermediate code file %s\n",
	      cname);
      exit(1);
   }
   if ((asmcode = fopen(aname, "w")) == NULL) {
      fprintf(stderr, "Cannot open assembler code file %s\n",
	      aname);
      exit(1);
   }

   /* read code file into code array */
   readcode(&count);

   /* check, which instructions should have labels */
   checklabels(count);

   /* assembler prolog 1 */
   prolog1();

   /* first pass : generate strings in data segment */
   genstrings(count);

   /* assembler prolog 2 */
   prolog2();

   /* second pass: generate assembler code for
      intermediate code instructions */
   strno = 0;
   for (pc=0; pc<=count; pc++) {

      /* output pcode instruction as comment,
	 if required by user */
      if (comment) gencomm(pc);

      /* generate label, if necessary */
      if (code[pc].lab) genlab(pc);

      switch (code[pc].o) {

	 case ADD : g_addsub(ADD);
		    break;
	 case SUB : g_addsub(SUB);
		    break;
	 case MPY : g_mpy();
		    break;
	 case DVD : g_dvd();
		    break;
	 case NEG : g_neg();
		    break;
	 case ODD : g_odd();
		    break;
	 case EQL : g_rel(EQL);
		    break;
	 case NEQ : g_rel(NEQ);
		    break;
	 case LSS : g_rel(LSS);
		    break;
	 case GTR : g_rel(GTR);
		    break;
	 case LEQ : g_rel(LEQ);
		    break;
	 case GEQ : g_rel(GEQ);
		    break;
	 case LIT : g_lit(code[pc].a);
		    break;
	 case RET : g_ret();
		    break;
	 case CAL : g_cal(code[pc].l, code[pc].a);
		    break;
	 case LOD : g_lod(code[pc].l, code[pc].a);
		    break;
	 case STO : g_sto(code[pc].l, code[pc].a);
		    break;
	 case INT : g_int(code[pc].a, pc);
		    break;
	 case JPU : g_jpu(code[pc].a);
		    break;
	 case JPC : g_jpc(code[pc].a);
		    break;
	 case INP : g_inp();
		    break;
	 case PRN : g_prn();
		    break;
	 case PRS : g_prs(code[pc].a, &pc);
		    break;
	 case PRL : g_prl();
		    break;
     default  :  fprintf(stderr,
			     "Unknown opcode %d\n",
			     code[pc].o);
		     exit(1);
      } /* switch */
      if (pc == 0)           /* first CAL */
      {
	 ga(0, ";");
	 ga(1, "call    endprocess");
      }
   }

   /* assembler epilog */
   epilog();

   /* close files */
   fclose(intcode);
   fclose(asmcode);
   return;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -