📄 pl0asm.c
字号:
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 + -