📄 pl0asm.c
字号:
/*******************************************************************
Program : Recursive Descent Compiler for PL/0
Module : PL0ASM - Code generator: intermediate (postfix) code
-> 80X86 assembler code for MS-DOS
File : pl0asm.c
Compiler: Borland C 3.1 - 4.5, GNU C 2.7.1
Author : H. Weber
Revision: Aug. 1998
********************************************************************/
#include <stdio.h>
#include <string.h>
#include "pl0code.h"
#define codemax 1000
FILE *asmcode, *intcode;
struct instr {
int o; /* opcode */
int l; /* level of declaration */
int a; /* rel. address in DSA */
int lab; /* label necessary */
char oc[4]; /* mnemonic for comment */
};
struct instr code[codemax];
int strno = 0; /* number of strings */
int label = 0; /* curr. number of label */
int currdata; /* number of current data objects */
int comment = 0; /* comment flag */
int os2 = 0; /* OS/2 flag */
char currproc[6]; /* name of current procedure */
void readcode(int *count)
/* read intermediate code */
{
int no, o, k;
char oc[4];
*count = 0;
while (!feof(intcode) && *count < codemax) {
k = fscanf(intcode, "%3d %3s %2d %5d",
&no, oc, &code[*count].l,
&code[*count].a);
if (k < 4) break;
if (strcmp(oc, "NUL") == 0) o = NUL;
else if (strcmp(oc, "ADD") == 0) o = ADD;
else if (strcmp(oc, "SUB") == 0) o = SUB;
else if (strcmp(oc, "MPY") == 0) o = MPY;
else if (strcmp(oc, "DVD") == 0) o = DVD;
else if (strcmp(oc, "NEG") == 0) o = NEG;
else if (strcmp(oc, "ODD") == 0) o = ODD;
else if (strcmp(oc, "EQL") == 0) o = EQL;
else if (strcmp(oc, "NEQ") == 0) o = NEQ;
else if (strcmp(oc, "LSS") == 0) o = LSS;
else if (strcmp(oc, "GTR") == 0) o = GTR;
else if (strcmp(oc, "LEQ") == 0) o = LEQ;
else if (strcmp(oc, "GEQ") == 0) o = GEQ;
else if (strcmp(oc, "LIT") == 0) o = LIT;
else if (strcmp(oc, "RET") == 0) o = RET;
else if (strcmp(oc, "CAL") == 0) o = CAL;
else if (strcmp(oc, "LOD") == 0) o = LOD;
else if (strcmp(oc, "STO") == 0) o = STO;
else if (strcmp(oc, "INT") == 0) o = INT;
else if (strcmp(oc, "JPU") == 0) o = JPU;
else if (strcmp(oc, "JPC") == 0) o = JPC;
else if (strcmp(oc, "INP") == 0) o = INP;
else if (strcmp(oc, "PRN") == 0) o = PRN;
else if (strcmp(oc, "ASC") == 0) o = ASC;
else if (strcmp(oc, "PRS") == 0) o = PRS;
else if (strcmp(oc, "PRL") == 0) o = PRL;
else {
fprintf(stderr, "Unknown opcode symbol %s\n", oc);
exit(1);
}
strcpy(code[*count].oc, oc);
code[(*count)++].o = o;
}
if (*count == codemax) {
fprintf(stderr, "Program too long.");
exit(1);
}
(*count)--;
}
void checklabels(int count)
{
int i, oc;
for (i=0; i<=count; i++)
code[i].lab = 0;
for (i=0; i<=count; i++) {
oc = code[i].o;
if (oc == JPU || oc == JPC )
code[code[i].a].lab = 1;
}
}
void gl(char *buf)
{
sprintf(buf, "m%03d", ++label);
}
void ga(int col, char *s)
{
char s1[80] ;
if (col == 1) {
strcpy(s1, " ");
strcat(s1, s);
}
else strcpy(s1, s);
fprintf(asmcode, "%s\n", s1);
}
void gencomm(int pc)
{
char s[50];
sprintf(s, "; ---- %03d %s %2d %3d", pc,
code[pc].oc, code[pc].l, code[pc].a);
ga(0, s);
}
void genlab(int pc)
{
char buf[5];
sprintf(buf, "l%03d:", pc);
ga(0, buf);
}
void genstrings(int count)
{
int pc = 0;
int j, l;
char s[80], s3[100];
while (pc <= count) {
if (code[pc].o == PRS) {
s[0] = '\'';
l = code[pc].a;
for (j=1; j<=l; j++)
s[j] = code[pc+j].a;
s[l+1] = '$';
s[l+2] = '\'';
s[l+3] = 0;
strno++;
sprintf(s3, "str%02d db ", strno);
strcat(s3, s);
ga(0, s3);
pc+= code[pc].a;
}
else pc++;
}
}
void g_addsub(int op)
{
ga(1, "pop ax ");
ga(1, "mov bp,sp ");
if (op == ADD)
ga(1, "add [bp],ax");
else
ga(1, "sub [bp],ax");
}
void g_mpy()
{
ga(1, "pop ax ");
ga(1, "mov bp,sp ");
ga(1, "imul word ptr [bp]");
ga(1, "mov [bp],ax ");
}
void g_dvd()
{
ga(1, "mov bp,sp");
ga(1, "pop ax ");
ga(1, "pop ax ");
ga(1, "cwd ");
ga(1, "idiv word ptr [bp]");
ga(1, "push ax ");
}
void g_neg()
{
ga(1, "pop ax");
ga(1, "neg ax");
ga(1, "push ax");
}
void g_odd()
{
ga(1, "pop ax ");
ga(1, "cwd ");
ga(1, "mov bx, 2");
ga(1, "idiv bx ");
ga(1, "push dx ");
}
void g_rel(int op)
{
char s[30];
char rel1[5], rel2[5];
gl(rel1);
gl(rel2);
ga(1, "pop ax ");
ga(1, "pop bx ");
ga(1, "cmp bx, ax ");
switch(op) {
case EQL : strcpy(s, "je "); break;
case NEQ : strcpy(s, "jne"); break;
case LSS : strcpy(s, "jl "); break;
case GTR : strcpy(s, "jg "); break;
case LEQ : strcpy(s, "jle"); break;
case GEQ : strcpy(s, "jge"); break;
}
strcat(s, " ");
strcat(s, rel1);
ga(1, s);
ga(1, "sub ax, ax");
strcpy(s, "jmp ");
strcat(s, rel2);
ga(1, s);
strcpy(s, rel1);
strcat(s, ": mov ax, 1");
ga(0, s);
strcpy(s, rel2);
strcat(s, ": push ax");
ga(0, s);
}
void g_lit(int a)
{
char s[20];
sprintf(s, "mov ax, %d", a);
ga(1, s);
ga(1, "push ax");
}
void g_ret()
{
char s[20];
// int i;
sprintf(s, "add sp, %d", 2*currdata);
ga(1, s);
ga(1, "ret"); /* Return */
sprintf(s, "%s endp", currproc); /* Ende Prozedur */
ga(0, s);
ga(0, ";");
}
void g_cal(int l, int a)
{
char s[100];
sprintf(s, "mov cx, %d", l);
ga(1, s);
ga(1, "call p_sbs ");
ga(1, "push dx ");
ga(1, "mov bp, sp ");
ga(1, "mov ax, [base]");
ga(1, "push ax ");
ga(1, "mov [base], bp");
sprintf(s, "call pr%03d", a);
ga(1, s);
ga(1, "pop dx");
ga(1, "mov [base], dx");
ga(1, "pop dx");
}
void g_lod(int l, int a)
{
char s[80];
if (l == 0)
ga(1, "mov bp, [base]");
else {
sprintf(s, "mov cx, %d", l);
ga(1, s);
ga(1, "call p_sbs");
ga(1, "mov bp, dx ");
}
sprintf(s, "push word ptr [bp-2*%d]", a);
ga(1, s);
}
void g_sto(int l, int a)
{
char s[80];
ga(1, "pop ax ");
if (l == 0)
ga(1, "mov bp, [base]");
else {
sprintf(s, "mov cx, %d", l);
ga(1, s);
ga(1, "call p_sbs ");
ga(1, "mov bp, dx");
}
sprintf(s, "mov word ptr [bp-2*%d], ax", a);
ga(1, s);
}
void g_int(int a, int pc)
{
char s[20];
sprintf(currproc, "pr%03d", pc);
sprintf(s, "%s proc", currproc);
ga(0, s);
sprintf(s, "sub sp, %d", 2*a);
ga(1, s);
currdata = a;
}
void g_jpu(int a)
{
char s[80];
sprintf(s, "jmp far ptr l%03d", a);
ga(1, s);
}
void g_jpc(int a)
{
char s[80], jpc1[6], jpc2[6];
gl(jpc1);
gl(jpc2);
ga(1, "pop ax ");
ga(1, "cmp ax, 0 ");
strcpy(s, "je ");
strcat(s, jpc1);
ga(1, s);
strcpy(s, "jmp ");
strcat(s, jpc2);
ga(1, s);
strcat(jpc1, ":");
sprintf(s, "%s jmp far ptr l%03d",
jpc1, a);
ga(0, s);
strcat(jpc2, ":");
ga(0, jpc2);
}
void g_inp()
{
ga(1, "mov bx, offset buffer");
ga(1, "mov al, [blen] ");
ga(1, "call instring ");
ga(1, "mov bx, offset buffer");
ga(1, "sub al, 2");
ga(1, "mov ch, 0 ");
ga(1, "mov cl, al ");
ga(1, "call string2number ");
ga(1, "push ax ");
}
void g_prn()
{
ga(1, "pop ax "); /* Zahl */
ga(1, "mov cx, 5 "); /* L刵ge */
ga(1, "call printint ");
}
void g_prs(int a, int *pc)
{
char s[80];
sprintf(s, "mov bx, offset str%02d", ++strno);
ga(1, s);
ga(1, "call outstring");
*pc += a; /* overread ASC opcodes */
}
void g_prl()
{
ga(1, "mov bx, offset crlf");
ga(1, "call outstring ");
}
void prolog1()
{
ga(0, "; Assembler prolog");
if (os2) {
ga(0, ";Generated by PL0ASM for MS OS/2 1.X");
ga(1, ".model small, pascal, os_os2");
ga(1, "includelib os2.lib");
ga(1, "include os2.inc");
} else {
ga(0, ";Generated by PL0ASM for MS-DOS 3.X, 4.X, 5.X");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -