Приложение 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; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!