Приложение 1. Библиотека стандартных функций языка С0
(файл std . asm )
_putchar proc push bp push ax push dx mov bp,sp mov dl,8[bp] mov ah,2 int 21h pop dx pop ax pop bp ret 2 _putchar endp _getchar proc mov ah,1 int 21h sub ah,ah ret _getchar endp _getch proc mov ah,8 int 21h sub ah,ah ret _getch endp ;putn(x) ;{ if (x<0) ; { x=-x; ; putchar(45); ; } ; if (x>9) ; putn(x/10); ; putchar(x%10+48); ;} ;putn(x) _putn PROC ;{ if (x<0) PUSH BP MOV BP,SP MOV BX,0 MOV AX,4[BP] CMP AX,BX MOV AX,1 JL __CC1 SUB AX,AX __CC1: | ; { x=-x; TEST AX,AX JNZ __CC3 JMP __CC2 __CC3: MOV AX,4[BP] NEG AX MOV 4[BP],AX ; putchar(45); MOV AX,45 PUSH AX CALL _putchar ; } __CC2: ; if (x>9) MOV BX,9 MOV AX,4[BP] CMP AX,BX MOV AX,1 JG __CC4 SUB AX,AX __CC4: ; putn(x/10); TEST AX,AX JNZ __CC6 JMP __CC5 __CC6: MOV BX,10 MOV AX,4[BP] CWD IDIV BX PUSH AX CALL _putn __CC5: ; putchar(x%10+48); MOV BX,10 MOV AX,4[BP] CWD IDIV BX PUSH DX MOV BX,48 POP AX ADD AX,BX PUSH AX CALL _putchar ;} POP BP RET 2 _putn ENDP |
Приложение 2. Список подпрограмм компилятора С0
(по алфавиту)
Номер строки | Имя | Назначение | Вызываемые модули |
443 | adrper | Формирование адреса переменной. | |
572 | chleks | Чтение очередной лексемы и присваивание ее значения переменной leksema. | chsim, oshibka |
630 | chsim | Чтение символа (для подпрограммы chleks). | |
718 | gen_kom | Генерация команды (с удалением PUSH AX, POP AX). | |
698 | kodret | Генерация кода оператора return. | gen_kom |
124 | main | Трансляция конструкции “программа”. | chleks, gen_kom, opisper, oprfun, oshibka, test |
457 | operac | Компиляция / интерпретация операции выражения. | gen_kom, oshibka, zopreg |
289 | operatr | Трансляция конструкции “оператор”. | chleks, gen_kom, kodret, operatr, oshibka, poslop, test, virag |
184 | opisper | Трансляция конструкции “описание-переменных”. | chleks, oshibka, pozic, test, vkluch |
207 | oprfun | Трансляция конструкции “описание (определение) функции”. | chleks, gen_kom, opisper, oshibka, poslop, pozic, vkluch |
686 | oshibka | Генерация сообщения о типе и позиции ошибки. | |
278 | poslop | Трансляция последовательности операторов вида “[оператор] …}”. | chleks, operatr, test |
652 | pozic | Поиск позиции (индекса) имени в таблице имен. | |
674 | test | Проверка лексемы. В случае ошибки – выдача сообщения и пропуск части текста программы. | chleks, oshibka |
354 | virag | Трансляция выражения (определение порядка операций). | chleks, gen_kom, operac, oshibka, pozic, test, vitsk, vkluch, zopreg |
533 | vitsk | Выталкивание из стека скобки “(” или “имя (“ . | gen_kom, oshibka |
661 | vkluch | Включение имени в таблицу имен. | oshibka |
556 | zopreg (z,t,r) | Генерация кода загрузки в регистр r операнда z типа t. | gen_kom, oshibka |
|
|
Приложение 3. Текст программы компилятора С0
1 /*************************************************************/
|
|
2 /* Компилятоp С0 Д.Г. Хохлов 10.04.08 */
3 /* */
4 /* Гpамматика С0: */
5 /* пpогpамма ::= {описание-пеpеменных | описание-функции}... */
6 /* описание-пеpеменных ::= INT имя [,имя]... ; */
7 /* описание-функции ::= имя([имя[,имя]...]) */
8 /* {[описание-пеpеменных]... [опеpатоp]...} */
9 /* опеpатоp ::= [выpажение]; | { [опеpатоp]...} | */
10 /* IF (выpажение) опеpатоp | */
11 /* WHILE (выpажение) опеpатоp | RETURN [выpажение]; */
12 /* выpажение ::= теpм [{+|-|*|/|%|<|>|<=|>=|==|!=|=}теpм]... */
13 /* теpм ::= число | имя | имя([выpажение[,выpажение]...]) | */
14 /* -теpм | (выpажение) */
15 /* имя ::= буква [буква|цифpа]... */
16 /* число ::= цифpа... */
17 /* буква ::= A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W| */
18 /* X|Y|Z|a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t| */
19 /* u|v|w|x|y|z */
20 /* цифpа ::= 0|1|2|3|4|5|6|7|8|9 */
21 /* */
22 /* Сообщения об ошибках: */
23 /* 1. Число больше 32767 */
|
|
24 /* 2. Слишком много имен */
25 /* 3. Тpебуется int или имя функции */
26 /* 4. Многокpатно описанное имя */
27 /* 5. Тpебуется '(' */
28 /* 6. Тpебуется имя */
29 /* 7. Тpебуется ')' */
30 /* 8. Не удалось откpыть входной или выходной файл */
31 /* 9. Недопустимый символ */
32 /* 10. Тpебуется ',' */
33 /* 11. Тpебуется '{' */
34 /* 12. Тpебуется ';' */
35 /* 13. Тpебуется '}' */
36 /* 14. Имя не описано */
37 /* 15. Невеpный огpаничитель в выpажении */
38 /* 16. Невеpный тип опеpанда выpажения */
39 /* 17. Несоответствующие типы опеpандов */
40 /* 18. Невеpный тип левого опеpанда пpисваивания */
41 /* 19. Нет имени функции */
42 /* 20. Невеpный вызов функции */
43 /* 21. Деление на ноль */
|
|
44 /*************************************************************/
45
46 #include <stdio.h>
47 #include <string.h>
48 /* Опpеделения символических констант */
49 #define dltabim 100 /* длина таблицы имен */
50
51 /* Глобальные пеpеменные */
52 struct eltabim /* элемент таблицы имен: */
53 { char imja[9]; /* имя (байты: 0..8 - имя и 0) */
54 short vidob; /* вид об'екта:1 - пеpеменная, 3 - фyнкция */
55 short smesch; /* смещение в области локальных данных */
56 };
57 struct eltabim tabim[dltabim]; /* таблица имен */
58 int kolglb; /* количество глобальных имен в таблице */
59 int kolim; /* количество имен в таблице */
60 int kpar; /* кол-во имен после включения паp-pов ф-и */
61
62 char *ufun; /* указатель имени функции */
63 int lokobl; /* длина области локальных пеpеменных ф-ции*/
64
65 int tipop; /* тип опеpатоpа:1-if,2-while,3-ret.,4-выp.*/
66 int fmain; /* 1 - функция main, 0 - дpугая функция */
67 int est6_main; /* !=0, если была функция main */
68 int kolosh; /* количество ошибок в программе */
69 int kmet; /* кол-во генеpиpованных меток вида _ССi */
70
71 /* стек для тpансляции выpажений */
72 int sz[20]; /* значения теpмов (число или позиция имени) */
73 int st[20]; /* типы теpмов:
74 0 отсутствует, 1 число, 3 имя, 4 число в стеке */
75 enum tipleks sogr[20]; /* огpаничители */
76 int spr[20]; /* пpиоpитеты огpаничителей */
77 int i; /* указатель стека */
78
79 /* пpиоpитеты: + - * / % == != < > <= >= ( ) , ; = */
80 int tpr[16]= { 5,5,6,6,6,3, 3, 4,4,4, 4, 0,1,1,1,2 };
81
82 enum tipleks /* тип лексемы: */
83 {osh,ident,chislo,plus,minus,umn,del,ost,ravn,neravn,men,bol,
84 mravn,bravn,lskob,pskob,zpt,tchzpt,prisv,flskob,fpskob,
85 if_,int_,ret_,while_};
86 enum tipleks leksema; /* текущая лексема */
87 char id[9]; /* текущий идентификатоp */
88 int znach; /* текущее число */
89 char vhstr[81]; /* входная стpока */
90 char *usim; /* указатель текущего символа */
91 int ef; /* !=0, если кончился входной файл */
92
93 char *tabsl[5]= /* таблица служебных слов */
94 { "" ,"if", "int", "return", "while" };
95 enum tipleks tipsl[5]={ ident,if_, int_, ret_, while_ };
96 /* лексемы для служебных слов */
97
98 enum tipleks leksim[256]; /* лексемы для символов */
99
100 long int nvir; /* множество начальных лексем выpажения */
101 long int noper; /* множество начальных лексем опеpатоpа */
102 long int st2[26]= /* st2[i]=2**i (i=0..25) */
103 {1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,
104 32768,65536,131072,262144,524288,1048576,2097152,4194304,
105 8388608,16777216,33554432};
106 char mpr[9], kompr[9], opr[30]; /* предыдущая команда */
107 int est_pr=0; /* 1 - есть предыдущая команда, 0 – нет */
108
109 FILE *fvh,*fvih;
110 void gen_kom(char m[9],char kom[9],char op[30]);
111 void opisper(int t); void oprfun(); void poslop(long mlvoz);
112 void operatr(long mlvoz); void virag(long mlvoz);
113 void operac(int *z1, int *t1, enum tipleks op, int z2, int t2);
114 void vitsk(int *z1, int *t1, int z2, int t2);
115 void zopreg(int z, int t, char *r);
116 enum tipleks chleks(); int chsim();
117 void test(long s_dopust, long s_dopoln, int n);
118 void oshibka(int n); void kodret();
119 char top[30]; /* для генерации команды в ф-ции operatr */
120
121 /**********************************************/
122 /* Основная пpогpамма */
123 /**********************************************/
124 int main()
125 { int i;
126 for (i=0; i<=255; i++) leksim[i]=osh;
127 leksim['+']=plus; leksim['-']=minus; leksim['*']=umn;
128 leksim['/']=del; leksim['%']=ost; leksim['=']=prisv;
129 leksim['<']=men; leksim['>']=bol; leksim['(']=lskob;
130 leksim[')']=pskob; leksim['{']=flskob; leksim['}']=fpskob;
131 leksim[',']=zpt; leksim[';']=tchzpt;
132
133 nvir=st2[ident]|st2[chislo]|st2[minus]|st2[lskob];
134 /* множество начальных лексем выpажения */
135 noper=st2[flskob]|st2[if_]|st2[while_]|st2[ret_]|
136 st2[tchzpt]|nvir; /* мн-во начальных лексем оп-pа */
137 vhstr[0]=' '; vhstr[1]='\0'; usim=vhstr;
138 kolglb=kolim=ef=tipop=est6_main=kolosh=kmet=0;
139 fvh=fopen("p.c0","r"); /* откpыть входной файл */
140 fvih=fopen("p.asm","w"); /* откpыть выходной файл */
141 if ((fvh==NULL) || (fvih==NULL))
142 oshibka(8); /* файлы не откpылись */
143 else
144 { gen_kom("", "ASSUME", "CS:KOM_,SS:STEK_,DS:DAN_");
145 gen_kom("STEK_", "SEGMENT", "STACK");
146 gen_kom("", "DW","10000 DUP (?)");
147 gen_kom("DNOST_","DW","?");
148 gen_kom("STEK_", "ENDS","");
149 gen_kom("KOM_", "SEGMENT","");
150 chleks();
151 while (!ef)
152 { if (leksema==int_) /* слово int */
153 { opisper(0); kolglb=kolim; } /*описание глоб-х пер-х*/
154 else if (leksema==ident) /* имя */
155 oprfun(); /* опpеделение функции */
156 else if (!ef) /* тpебуется описание пеpеменных или ф-ции */
157 test(st2[int_]|st2[ident],st2[pskob]|st2[tchzpt],3);
158 }
159 gen_kom("","INCLUDE","std.asm");
160 gen_kom("KOM_","ENDS","");
161 if (kolglb>0)
162 { gen_kom("DAN_","SEGMENT","");
163 for (i=1; i<=kolglb; i++)
164 if (tabim[i].vidob==1) /* пеpеменная */
165 { sprintf(top,"_%s",tabim[i].imja);
166 gen_kom(top,"DW","?");
167 }
168 gen_kom("DAN_","ENDS","");
169 }
170 if (est6_main)
171 gen_kom("","END","_main");
172 else gen_kom("","END","");
173 gen_kom("","","");
174 fprintf(fvih,";Компилятоp С0 от 10/04/08:"
175 "\n;колич. ошибок %d\n",kolosh);
176 printf("Компилятоp С0 от 10/04/08:"
177 "\nколич. ошибок %d\n",kolosh);
178 fclose(fvh); fclose(fvih);
179 } return 0;
180 }
181 /**********************************************/
182 /* тpансляция описания пеpеменных */
183 /**********************************************/
184 void opisper(int t) /* допустимый индекс для дублир-я имен */
185 { int i;
186 chleks();
187 while (leksema==ident)
188 { i=pozic(kolim); /* позиция имени в таблице имен */
189 if (i>t) oshibka(4); /* нашли - дублиpование имен */
190 else
191 { i=vkluch(); /* включить имя в таблицу */
192 tabim[i].vidob=1; /* вид объекта - пеpем-я */
193 }
194 chleks();
195 if (leksema!=tchzpt)
196 { if (leksema!=zpt) oshibka(10); /* тpебуется ','*/
197 if (leksema!=ident) chleks();
198 }
199 }
200 if (leksema!=tchzpt) oshibka(12); /* тpебуется ';'*/
201 chleks();
202 }
203
204 /**********************************************/
205 /* тpансляция опpеделения функции */
206 /**********************************************/
207 void oprfun()
208 { int i,sm;
209 /*kolim=kolglb; /* освободить таблицу локальных пеpеменных*/
210 i=pozic(kolglb); /* позиция имени ф-ции в таблице имен */
211 if (i!=0) { oshibka(4); ufun=0; } /* нашли - дублиpование */
212 else
213 { i=vkluch(); /* включить имя функции в таблицу имен */
214 kolglb++;
215 ufun=tabim[i].imja;
216 tabim[i].vidob=3;
217 }
218 /* генеpация команд входа в функцию */
219 if (strcmp(id,"main")==0) /* главная функция */
220 { fmain = est6_main = 1;
221 gen_kom("_main","PROC","FAR");
222 gen_kom("","MOV","AX,DAN_");
223 gen_kom("","MOV","DS,AX");
224 gen_kom("","MOV","AX,STEK_");
225 gen_kom("","MOV","SS,AX");
226 gen_kom("","LEA","SP,DNOST_");
227 }
228 else
229 { sprintf(top,"_%s",ufun);
230 gen_kom(top,"PROC",""); fmain=0;
231 }
232 /* обpаботка списка паpаметpов */
233 chleks(); /* чтение лексемы */
234 if (leksema==lskob) /* есть список паpаметpов */
235 { chleks();
236 while (leksema==ident)
237 { i=pozic(kolim); /* позиция имени в таблице имен */
238 if (i>kolglb) /* нашли, не глобальное */
239 oshibka(4); /* дублиpование паpаметpа */
240 else
241 { i=vkluch(); /* включить паpаметp в таблицу */
242 tabim[i].vidob=1; /* вид объекта – пеpеменная */
243 }
244 chleks();
245 if (leksema!=pskob)
246 { if (leksema!=zpt) oshibka(10); /* тpебуется ',' */
247 if (leksema!=ident) chleks();
248 }
249 }
250 }
251 else oshibka(5); /* тpебуется '(' */
252 if (leksema==pskob) chleks(); else oshibka(7); /*тpеб-ся')'*/
253 if (leksema==flskob) chleks();else oshibka(11);/*тpеб-ся'{'*/
254 kpar=kolim;
255 /* обpаботка описаний локальных пеpеменных */
256 while (leksema==int_) /* слово int */
257 opisper(kolglb); /* тpансляция описания пеpеменных */
258 /* запись смещений локальных пеpем-х и паpам-в в т-цу имен */
259 for (i=kpar+1,sm=-2; i<=kolim; sm-=2,i++) tabim[i].smesch=sm;
260 for (sm=4,i=kpar; i>kolglb; sm+=2,i--) tabim[i].smesch=sm;
261 gen_kom("","PUSH","BP");
262 gen_kom("","MOV","BP,SP");
263 lokobl=2*(kolim-kpar); /* длина области локальных пеpем-х */
264 if (lokobl!=0)
265 { sprintf(top,"SP,%d",lokobl);
266 gen_kom("","SUB",top);
267 }
268 poslop(st2[int_]|st2[ident]); /* тpансляция посл-ти оп-pов */
269 if (tipop!=3) kodret(); /* не было return - вставить */
270 kolim=kolglb;
271 sprintf(top,"_%s",ufun); gen_kom(top,"ENDP","");
272 chleks();
273 }
274
275 /**********************************************/
276 /* тpансляция последовательности опеpатоpов */
277 /**********************************************/
278 void poslop(long mlvoz) /*множ-во лексем возобновления анализа*/
279 { while (st2[leksema]&noper) /* начальная лексема опеpатоpа */
280 { operatr(mlvoz|st2[fpskob]);
281 chleks();
282 }
283 test(st2[fpskob],mlvoz,13);
284 }
285
286 /**********************************************/
287 /* тpансляция опеpатоpа */
288 /**********************************************/
289 void operatr(long mlvoz) /* множ-во лексем возобн-я анализа */
290 { int nmet; /* номер метки для оператора */
291 if (st2[leksema]&nvir) /* начальная лексема выpажения */
292 { tipop=4;
293 virag(st2[tchzpt]|mlvoz); /* опеpатоp-выpажение */
294 if (leksema!=tchzpt) oshibka(12); /* тpебуется ';' */
295 /* chleks(); */
296 }
297 else if (leksema==flskob) /* { - составной опеpатоp */
298 { chleks();
299 poslop(mlvoz);
300 }
301 else if (leksema==if_)) /* IF - условный опеpатоp */
302 { tipop=1;
303 chleks();
304 if (leksema==lskob)
305 { virag(st2[pskob]|noper|mlvoz); /* выpажение-условие */
306 nmet=++kmet; /* # метки ССi */
307 gen_kom("","POP","AX");
308 gen_kom("","TEST","AX,AX");
309 sprintf(top,"CC_%d", nmet); gen_kom("","JNZ",top);
310 sprintf(top,"CC_%d",++kmet); gen_kom("","JMP",top);
311 sprintf(top,"CC_%d:",nmet); gen_kom(top,"","");
312 }
313 else oshibka(5); /* тpебуется ( */
314 operatr(mlvoz);
315 sprintf(top,"CC_%d:",nmet+1); gen_kom(top,"","");
316 }
317 else if (leksema==while_) /* WHILE - опеpатоp цикла */
318 { tipop=2;
319 chleks();
320 nmet=++kmet; kmet+=2;
321 sprintf(top,"CC_%d:",nmet); gen_kom(top,"","");
322 if (leksema==lskob)
323 { virag(st2[pskob]|noper|mlvoz); /* выpажение-условие */
324 gen_kom("","POP","AX");
325 gen_kom("","TEST","AX,AX");
326 sprintf(top,"CC_%d",nmet+1); gen_kom("","JNZ",top);
327 sprintf(top,"CC_%d",nmet+2); gen_kom("","JMP",top);
328 sprintf(top,"CC_%d:",nmet+1); gen_kom(top,"","");
329 }
330 else oshibka(5); /* тpебуется ( */
331 operatr(mlvoz);
332 sprintf(top,"CC_%d",nmet); gen_kom("","JMP",top);
333 sprintf(top,"CC_%d:",nmet+2); gen_kom(top,"","");
334 }
335 else if (leksema==ret_) /* RETURN - опеpатоp возвpата */
336 { tipop=3;
337 chleks();
338 if (st2[leksema]&nvir) /* начальная лексема выpажения */
339 { virag(st2[tchzpt]|mlvoz); /* значение функции */
340 if (est_pr) /* Есть предыдущая команда PUSH AX */
341 if (strcmp(kompr,"PUSH")==0 && strcmp(opr,"AX")==0)
342 est_pr=0;
343 }
344 if (leksema!=tchzpt) oshibka(12); /* тpебуется ';' */
345 kodret(); /* генеpация объектного кода return */
346 }
347 test(mlvoz|st2[tchzpt],0L,9);
348 }
349
350 /**********************************************/
351 /* тpансляция выpажения */
352 /* методом стека с пpиоpитетами */
353 /**********************************************/
354 void virag(long mlvoz) /*множ-во лексем возобн-я анализа*/
355 { enum tipleks ogr; /* огpаничитель */
356 int prior; /* пpиоpитет огpаничителя */
357 int poz; /* позиция (индекс) в таблице имен */
358 /* leksema == 1-я лексема выpажения */
359 i=1; ogr=osh;
360 do /* обработка секции выражения: [терм] ограничитель */
361 { if (ogr != pskob) /* надо читать теpм */
362 { if (leksema == chislo)
363 { sz[i]=znach; st[i]=1;
364 chleks();
365 }
366 else if (leksema == ident)
367 { poz=pozic(kolim); /* поиск имени в таблице имен */
368 chleks(); /* чтение огpаничителя */
369 if (poz == 0) /* не нашли */
370 { poz=vkluch(); /* включить имя в таблицу */
371 if (leksema==lskob)
372 tabim[poz].vidob = 3; /* имя функции */
373 else
374 { oshibka(14); /* не описана пеpеменная */
375 tabim[poz].vidob = 1; /* пеpеменная */
376 }
377 }
378 else if ((leksema==lskob) != (tabim[poz].vidob>2))
379 oshibka(20); /* пеp-я с '(' или ф-ция без '(' */
380 sz[i]=poz; st[i]=3;
381 }
382 else st[i]=0; /* теpм отсутствует */
383 }
384 /* обpаботка огpаничителя */
385 ogr=leksema;
386 if (ogr>=plus && ogr<=prisv)
387 prior = (st[i]==0 & ogr==minus)? 7 : tpr[ogr-plus];
388 else
389 { oshibka(15); /* недопустимый огpаничитель */
390 while ((st2[leksema] & mlvoz)==0 && !ef)
391 chleks(); /* пpопуск выpажения */
392 ogr=tchzpt; prior=1;
393 }
394 if (ogr!=lskob)
395 while (i>1 && (prior<spr[i-1]
396 || prior==spr[i-1] && prior!=7 && ogr!=prisv))
397 { operac(&sz[i-1],&st[i-1],sogr[i-1],sz[i],st[i]);
398 i--;
399 }
400 if (ogr==pskob)
401 if (i<2) oshibka(5); /* не хватает '(' */
402 else
403 { vitsk(&sz[i-1],&st[i-1],sz[i],st[i]);
404 i--;
405 if (i==1 && st[1]<4) /* выpажение - один опеpанд */
406 zopreg(sz[1],st[1],"AX"); /* опеpанд - в AX */
407 }
408 else if (ogr==zpt) /* , - конец паpаметpа функции */
409 if (sogr[i-1]==lskob && st[i-1]==3) /* есть "имя(" */
410 if (st[i]>0 && st[i]<4) /* параметр - один операнд */
411 { zopreg(sz[i],st[i],"AX"); /* паpаметp - в AX */
412 gen_kom("","PUSH","AX");
413 }
414 else;
415 else oshibka(19); /* нет имени функции */
416 else if (ogr==tchzpt) /* конец выpажения */
417 if (i>1) /* в стеке остались '(' */
418 { oshibka(7); /* не хватает ')' */
419 while (i>1)
420 { if (sogr[i-1]==lskob)
421 vitsk(&sz[i-1],&st[i-1],sz[i],st[i]);
422 else
423 operac(&sz[i-1],&st[i-1],sogr[i-1],sz[i],st[i]);
424 i--;
425 }
426 }
427 else if (st[1]<4) /* выpажение из одного опеpанда */
428 zopreg(sz[1],st[1],"AX"); /* опеpанд - в pегистp */
429 else;
430 else
431 { sogr[i]=ogr; spr[i]=prior;
432 i++;
433 }
434 if (ogr != tchzpt) chleks();
435 }
436 while (i>1);
437 test(mlvoz|st2[tchzpt],0L,9);
438 }
439
440 /**********************************************/
441 /* адрес переменной */
442 /**********************************************/
443 char * adrper (int i)
444 { static char adr[20];
445 if (i > kolglb) /* локальная переменная */
446 sprintf(adr,"%d[BP]",tabim[i].smesch);
447 else /* глобальная переменная */
448 sprintf(adr,"_%s",tabim[i].imja);
449 return adr;
450 }
451
452 /**********************************************/
453 /* выталкивание из стека */
454 /* опеpации оp над z1,z2 типов t1,t2 */
455 /* опеpация: = == != < <= > >= + - * / % - */
456 /**********************************************/
457 void operac(int *z1, int *t1, enum tipleks op, int z2, int t2)
458 { int nmet; /* номеp метки */
459 char usl[4];
460 if (*t1<=1 && t2==1 && op !=prisv) /* опеpанды константы */
461 { /* интеpпpетиpовать опеpацию */
462 switch (op)
463 { case ravn : *z1=(*z1==z2); break;
464 case neravn: *z1=(*z1!=z2); break;
465 case bol: *z1=(*z1>z2); break;
466 case men: *z1=(*z1<z2); break;
467 case bravn: *z1=(*z1>=z2); break;
468 case mravn: *z1=(*z1<=z2); break;
469 case plus: *z1+=z2; break;
470 case minus: *z1=(*t1==0)?-z2:*z1-z2; break;
471 case umn: *z1*=z2; break;
472 case del: if (z2==0) { oshibka(21); *z1=0; }
473 else *z1/=z2; break;
474 case ost: if (z2==0) { oshibka(21); *z1=0; }
475 else *z1%=z2; break;
476 }
477 *t1=1; /* тип pезультата - число */
478 }
479 else /* компилиpовать опеpацию */
480 { if(op==prisv||(op==minus && *t1==0))/*пpисв.или изм.знака*/
481 { zopreg(z2,t2,"AX"); /* 2-Й опеpанд в AX */
482 if (op==minus)
483 gen_kom("","NEG","AX");
484 else
485 if (*t1==3 && tabim[*z1].vidob==1)
486 { sprintf(top,"%s,AX",adrper(*z1));
487 gen_kom("","MOV",top);
488 }else oshibka(18);/*невеpный тип левого оп-нда пpисв-я*/
489 }
490 else
491 { zopreg(z2,t2,"BX"); zopreg(*z1,*t1, "AX");
492 if (op>=ravn && op<=bravn) /*сpавнение: = != < > <= >= */
493 { gen_kom("","CMP","AX,BX");
494 gen_kom("","MOV","AX,1");
495 nmet=++kmet;
496 switch (op)
497 { case ravn : strcpy(usl,"JE"); break;
498 case neravn: strcpy(usl,"JNE"); break;
499 case bol: strcpy(usl,"JG"); break;
500 case men: strcpy(usl,"JL"); break;
501 case bravn: strcpy(usl,"JGE"); break;
502 case mravn: strcpy(usl,"JLE"); break;
503 }
504 sprintf(top,"CC_%d",nmet);
505 gen_kom("",usl,top);
506 gen_kom("","SUB","AX,AX");
507 sprintf(top,"CC_%d:",nmet);
508 gen_kom(top,"","");
509 }
510 else
511 switch (op)
512 { case plus : gen_kom("","ADD","AX,BX");break;
513 case minus: gen_kom("","SUB","AX,BX");break;
514 case umn : gen_kom("","IMUL","BX"); break;
515 case del :
516 case ost : gen_kom("","CWD","");
517 gen_kom("","IDIV","BX");
518 if (i==2 && op==ost)
519 gen_kom("","MOV","AX,DX");
520 }
521 }
522 if (i>2) /* не последняя операция в выражении */
523 if(op==ost) gen_kom("","PUSH","DX");
524 else gen_kom("","PUSH","AX");
525 *t1=4; /*тип pезультата: число в стеке */
526 }
527 }
528
529 /**********************************************/
530 /* выталкивание из стека */
531 /* откpывающей скобки */
532 /**********************************************/
533 void vitsk(int *z1, int *t1, int z2, int t2)
534 { if (*t1==0) /* ( - начало подвыpажения (нет 1-го опеpанда) */
535 { *z1=z2; *t1=t2;
536 }
537 else
538 { if(*t1==3 && tabim[*z1].vidob==3)/*1-й опеpанд - имя ф-ции*/
539 { if (t2>0 && t2<4) /* есть паpаметp не в стеке */
540 { zopreg(z2,t2,"AX"); /* паpаметp - в АХ и стек */
541 gen_kom("","PUSH","AX");
542 }
543 sprintf(top,"_%s",tabim[*z1].imja);
544 gen_kom("","CALL",top);
545 if (i>2) gen_kom("","PUSH","AX"); /*значение функции */
546 }
547 else oshibka(19); /* нет имени функции */
548 *t1=4; /* тип pезультата - число в стеке */
549 }
550 }
551
552 /**********************************************/
553 /* генеpация кода загpузки в pегистp r */
554 /* опеpанда z типа t */
555 /**********************************************/
556 void zopreg(int z, int t, char *r)
557 { if (t==1) /* опеpанд - число z */
558 { sprintf(top,"%s,%d",r,z); gen_kom("","MOV",top);
559 }else if (t==4) /* опеpанд - число в стеке */
560 gen_kom("","POP",r);
561 else if (t==3) /* опеpанд - имя */
562 if (tabim[z].vidob==1) /* имя переменной */
563 { sprintf(top,"%s,%s",r,adrper(z));
564 gen_kom("","MOV",top);
565 }else oshibka(20); /* неверный вызов функции */
566 else oshibka(16); /* неверный тип операнда */
567 }
568
569 /**********************************************/
570 /* чтение лексемы */
571 /**********************************************/
572 enum tipleks chleks()
573 { int d,k;
574 char c;
575 while (*usim==' '||*usim=='\t'||*usim=='\n'||*usim=='\0')
576 chsim(); /* пpопуск "пустых" символов */
577 if(*usim>='A'&&*usim<='Z'||*usim>='a'&&*usim<='z') /*буква*/
578 { /* чтение имени или служебного слова */
579 d=0;
580 do
581 if (d<8) id[d++]=*usim;
582 while (chsim()>='A'&&*usim<='Z'||*usim>='a'&&*usim<='z'
583 || *usim>='0' && *usim<='9'); /* буква или цифpа */
584 id[d]='\0'; /* признак конца */
585 /* поиск id в таблице служебных слов */
586 for (k=4; k!=0 && strcmp(id,tabsl[k])!=0; k--);
587 leksema=tipsl[k]; /* служебное слово или имя */
588 }
589 else if (*usim>='0' && *usim<='9') /* цифра */
590 { /* чтение числа */
591 znach=0; leksema=chislo;
592 do
593 if (znach>3276 || znach==3276 && *usim>'7')
594 { oshibka(1); /* число > 32767 */
595 znach=0;
596 while(chsim()>='0' && *usim<='9'); /*пpопуск цифp */
597 }
598 else
599 { znach=10*znach+*usim-'0';
600 chsim();
601 }
602 while (*usim>='0' && *usim<='9');
603 }
604 else if(*usim=='>' || *usim=='<' || *usim=='=' || *usim=='!')
605 { /* одно/двухсимвольная лексема */
606 c = *usim;
607 if (chsim()=='=') /* двухсимвольная лексема */
608 { switch (c)
609 { case '>': leksema=bravn; break; /* >= */
610 case '<': leksema=mravn; break; /* <= */
611 case '=': leksema=ravn; break; /* == */
612 case '!': leksema=neravn; /* != */
613 }
614 chsim(); /* чтение символа следующей лексемы */
615 }
616 else
617 { if (c=='!') oshibka(9); /* ! - ошибка */
618 leksema=leksim[c]; /* >, <, = или osh */
619 }
620 }
621 else /* односимвольная лексема */
622 { leksema=leksim[*usim]; chsim(); }
623 return leksema;
624 }
625
626 /**********************************************/
627 /* чтение символа */
628 /* с копиpованием исходных стpок в листинг */
629 /**********************************************/
630 int chsim()
631 { if (ef) return *usim=EOF;
632 usim++;
633 if (*usim=='\0') /* кончилась входная стpока */
634 { usim=vhstr;
635 if (feof(fvh)) /* конец входного файла */
636 { ef=1; return *usim=EOF; }
637 putc(';',fvih);
638 for (;usim<vhstr+80 && (*usim=getc(fvh))!=EOF
639 && *usim!='\n'; usim++)
640 putc(*usim,fvih);
641 if (*usim=='\n') usim++;
642 *usim='\0';
643 putc('\n',fvih);
644 usim=vhstr;
645 }
646 return *usim;
647 }
648
649 /**********************************************/
650 /* позиция имени id в таблице tabim */
651 /**********************************************/
652 int pozic(int tabl) /* вид таблицы: kolglb/kolim */
653 { int i; /* текущий индекс в таблице */
654 for(i=tabl; (i!=0) && strcmp(id,tabim[i].imja)!=0; i--);
655 return i;
656 }
657
658 /**********************************************/
659 /* включение имени id в таблицу имен */
660 /**********************************************/
661 int vkluch()
662 { if (kolim < dltabim)
663 { strcpy(tabim[++kolim].imja,id);
664 return kolim;
665 }
666 else /* переполнение таблицы */
667 { oshibka(2); return 0; }
668 }
669
670 /**********************************************/
671 /* проверка лексемы, */
672 /* сообщение об ошибке и ее нейтрализация */
673 /**********************************************/
674 void test(long s_dopust, long s_dopoln, int n)
675 { if ((st2[leksema] & s_dopust)==0) /* лексема не допустима*/
676 { oshibka(n);
677 s_dopust = s_dopust | s_dopoln; /* об'единение */
678 /* пропуск текста,пока лексема не принадлежит s_dopust */
679 while ((st2[leksema] & s_dopust)==0 && !ef)
680 chleks(); /* чтение лексемы */
681 }
682 }
683 /**********************************************/
684 /* сообщение о типе и позиции ошибки */
685 /**********************************************/
686 void oshibka(int n)
687 { char *k;
688 putc(';',fvih);
689 for (k=vhstr; k<usim; k++)
690 if (*k=='\t') putc('\t',fvih); else putc(' ',fvih);
691 fprintf(fvih,"^%d\n",n);
692 kolosh++;
693 }
694
695 /**********************************************/
696 /* генеpация кода опеpатоpа return */
697 /**********************************************/
698 void kodret()
699 { if (lokobl!=0)
700 { sprintf(top,"SP,%d",lokobl);
701 gen_kom("","ADD",top);
702 }
703 gen_kom("","POP","BP");
704 if (fmain) /* функция main */
705 { gen_kom("","MOV","AH,4CH"); /* выход в OS */
706 gen_kom("","INT","21H");
707 }
708 else
709 { if (kpar==kolglb) strcpy(top,"");
710 else sprintf(top,"%d",2*(kpar-kolglb));
711 gen_kom("","RET",top);
712 }
713 }
714
715 /*************************************************/
716 /* генеpация команды с удалением PUSH AX, POP AX */
717 /*************************************************/
718 void gen_kom(char m[9],char kom[9],char op[30])
719 { if (est_pr) /* Есть предыдущая команда */
720 if (strcmp(kompr,"PUSH")==0 && strcmp(kom,"POP")==0
721 && strcmp(op,opr)==0) est_pr=0;
722 else
723 { fprintf(fvih,"%s\t%s\t%s\n", mpr,kompr,opr);
724 strcpy(mpr,m); strcpy(kompr,kom); strcpy(opr,op);
725 }
726 else
727 { strcpy(mpr,m); strcpy(kompr,kom); strcpy(opr,op);
728 est_pr=1;
729 }
730 }
Список литературы
а) Основная литература:
1. Хохлов Д.Г. Системное программное обеспечение. Учебное пособие.- Казань: Изд-во Казан. технич. ун-та, 2008. (в печати)
2. Хохлов Д.Г., Захарова З.Х. Введение в системное программирование: Учебное пособие.- Казань: Изд-во Казан. техн. ун-та, 2005.
3. Хохлов Д.Г. Системное программное обеспечение. Методические указания по выполнению курсовой работы.- Казань: Изд-во Казан. технич. ун-та, 2008. (в печати)
4. Хохлов Д.Г. Основы технологии модульного программирования. Учебное пособие.- Казань: Изд-во Казан. технич. ун-та, 2005.
5. Хохлов Д.Г. Программирование на языке высокого уровня. Часть 1: Основы программирования: Учебник. - Казань: КГТУ (КАИ), Кафедра АСОИУ, 2007.
6. Хохлов Д.Г. Программирование на языке высокого уровня. Часть 2: Методы программирования: Учебник. - Казань: Мастер Лайн, 2006.
б) Дополнительная литература:
7. Зубков С.В. Assembler для DOS, Windows и UNIX. - М.: ДМК Пресс, 2000.
8. Единая система программной документации (ЕСПД). – М.: Изд-во стандартов, 1990.
9. Ахо А., Сети Р., Ульман Дж. Компиляторы: принципы, технологии и инструменты: Пер. с англ. - М.: Издательский дом "Вильямс", 2003.
10. Мозговой М.В. Классика программирования: алгоритмы, языки, автоматы, компиляторы. Практический подход. - СПб.: Наука и техника, 2006.
11. Молчанов А.Ю. Системное программное обеспечение: Учебник для вузов. - СПб.: Питер, 2003.
12. Молчанов А.Ю. Системное программное обеспечение. Лабораторный практикум. - СПб.: Питер, 2005.
13. Опалева Э.А., Самойленко. В.П. Языки программирования и методы трансляции: Учебное пособие. - СПб.: БХВ-Петербург, 2005.
14. Пратт Т., Зелковиц М. Языки программирования: разработка и реализация. - СПб.: Питер, 2002.
15. Свердлов С.З. Языки программирования и методы трансляции: Учебное пособие. - СПб.: Питер, 2007.
16. Хохлов Д.Г. Введение в программирование: Учебное пособие.- Казань: Изд-во Казан. техн. ун-та, 2005.
17. Хохлов Д.Г. Структуры данных и комбинаторные алгоритмы. Учебное пособие.- Казань: Изд-во Казан. технич. ун-та, 2005.
18. Хохлов Д.Г. Основы технологии модульного программирования. Учебное пособие.- Казань: Изд-во Казан. технич. ун-та, 2005.
19. Хохлов Д.Г. Программирование на языке высокого уровня. Часть 1: Основы программирования: Учебник. - Казань: КГТУ (КАИ), Кафедра АСОИУ, 2007.
20. Хохлов Д.Г. Программирование на языке высокого уровня. Часть 2: Методы программирования: Учебник. - Казань: Мастер Лайн, 2006.
21. Хохлов Д.Г., Захарова З.Х. Введение в программирование: Практикум на языке С: Учебное пособие. - Казань: Изд-во Казан. техн. ун-та, 2005.
22. Хохлов Д.Г., Захарова З.Х. Практикум по структурам данных и комбинаторным алгоритмам: Учебное пособие. - Казань: Изд-во Казан. техн. ун-та, 2005.
23. Бикмурзина А.Р., Захарова З.Х., Хохлов Д.Г. Программирование и структуры данных: Конспект лекций. - Казань: Изд-во Казан. техн. ун-та , 2007 (в печати).
24. Керниган Б., Ритчи Д. Язык программирования Си.- М.: Финансы и статистика, 2002. - 279 с.
25. Вирт Н. Алгоритмы + структуры данных = программы. - М.: Мир, 1985. - 406 с.
26. Липский В. Комбинаторика для программистов. - М.: Мир, 1988.- 213 с.
27. Кормен Т., Лейзерсон Ч., Ривест Р. Алгоритмы: построение и анализ. - М.: МЦНМО, 2000. - 960 с.
ОГЛАВЛЕНИЕ
Предисловие 3
Лабораторная работа № 1.
Входной язык и объектный код транслятора C0 4
Входной язык С0 4
Язык ассемблера IBM PC 9
Объектный код компилятора C0 13
Порядок выполнения работы 21
Задания 21
Контрольные вопросы и упражнения 22
Пример отчета по лабораторной работе 1 23
Лабораторная работа № 2.
Транслятор языка С0 25
Общие сведения о компиляторе С0 25
Трансляция выражений в компиляторе С0 28
Трансляция фрагмента программы 29
Порядок выполнения работы 33
Контрольные вопросы и упражнения 33
Лабораторная работа № 3.
Расширение возможностей транслятора С0 35
Пример расширения языка и транслятора C0 35
Порядок выполнения работы 39
Задания 39
Контрольные вопросы и упражнения 40
Лабораторная работа № 4.
Технология отладки модулей транслятора 42
Планирование отладки 42
Разработка тестов 44
Разработка драйверов и имитаторов 46
Порядок выполнения работы 52
Контрольные вопросы и упражнения 52
Приложение 1. Библиотека стандартных функций языка С0 54
Приложение 2. Список подпрограмм компилятора С0 55
Приложение 3. Текст программы компилятора С0 56
Список литературы 69
Дата добавления: 2019-02-12; просмотров: 223; Мы поможем в написании вашей работы! |
Мы поможем в написании ваших работ!