Системное программное обеспечение. 2

Казанский государственный научно исследовательский технический университет им. А.Н.Туполева

Кафедра АСОИУ

 

 

 

 

 

 

 

 

Курсовая работа

по дисциплине

"Системное программное обеспечение"

 

 

 

 

 

 

 

 Выполнила:

                                                                      Студент: Фагмеева А.М.

гр.4452

                            Руководитель:

                                                                                       Мокшин В.В.

                                                                      Подпись: _______________

                                                                       Дата сдачи: _____________

 

 

 

Казань 2013

 

СОДЕРЖАНИЕ

 

  1. ЗАДАНИЕ……………………………………………………………..
  2. ОПИСАНИЕ ПРИМЕНЕНИЯ………………………………………..
    1. Общие сведения о трансляторе С0…………………………….
    2. Возможности языка C0………………………………………...
    3. Использование компилятора C0………………………………
    4. Сообщения об ошибках………………………………………...
  3. ОПИСАНИЕ ПРОГРАММЫ…………………………………………
    1. Описание новых возможностей языка C0…………………….

3.1.1 Тип данных: char………………………………………..…

3.1.2 Дополнительные операции: ++,--……………………...

3.1.3 if else…………………………………………………

3.1.4 Тип комментария: \\………………………………………...

3.1.5 Тип констант: 16……………………………………………

    1. Список подпрограмм транслятора С0 ………………………..
  1. ТЕСТИРОВАНИЕ ПРОГРАММЫ …………………………………..
  2. ЗАКЛЮЧЕНИЕ………………………………………………………..
  3. СПИСОК ЛИТЕРАТУРЫ………………………………………….....

3

3

3

3

4

5

6

5

5

6

12

14

15

17

21

22

23


 

 

  1. ЗАДАНИЕ

 

Расширить язык и транслятор С0, реализовав в них следующие возможности:

    • Тип данных: char
    • Тип констант: 16;
    • Операции: ++,--;
    • Оператор if else;
    • Комментарий: \\

 

 

  1. ОПИСАНИЕ ПРИМЕНЕНИЯ
    1. Общие сведения о трансляторе С0

 

Транслятор С0 переводит исходную программу с языка С0 на язык ассемблера IBM PC. Таким образом, использование языка ассемблера в качестве объектного языка делает его однопроходным и более удобным в понимании основных методов трансляции, избежав многочисленных деталей генерации машинного кода.

Транслятор написан на языке С и состоит из 18 подпрограмм, которые используют около 30 глобальных переменных.

Трансляция выражений в С0 производиться методом стека с приоритетом. Остальные конструкции языка (операторы и описания) транслируются методом рекурсивного спуска.

 

    1. Возможности языка С0

 

Входной язык С0 является подмножеством языка С и содержит данные только целочисленного типа, без массивов. Разрешаются глобальные и локальные переменные, функции с параметрами, рекурсия.

Параметры функции могут быть только входными, поэтому результат работы функции передается только в виде ее значения или присваивается глобальной переменной. Параметры не описываются.

Имеются следующие операторы: оператор-выражение, составной оператор, сокращённый условный оператор, цикл с предусловием, оператор возврата.

В выражениях допускаются:

    • арифметические операции:  +, -, *, /, %;
    • сравнения:  ==, !=, <, >, <=, >=;
    • присваивание:  =;
    • скобки:  ( ).

     Отсутствующие в языке  С0 логические операции И и  ИЛИ можно заменить * или + соответственно.

 

     Примечания.

  1. Служебные слова пишутся строчными буквами.
  2. Длина имени не ограничена, но учитываются не более 8 символов.
  3. Отсутствующий оператор return в конце описания функции вставляется автоматически.

 

     Грамматика языка СО.

программа               ::=    {описание-переменных [ описание-функции}...

описание-переменных     ::=     int имя [,имя]...;

описание-функции    ::=     имя ( [имя[,имя]...] )

{ [описание-переменных]...[оператор]... }

оператор    ::= [выражение]; | { [оператор]... } |

if (выражение) оператор | return [выражение];

while (выражение) оператор

выражение    ::=   терм [{+|-|*|/|%|<|>|<=|>=|==|!=|=}терм]…

терм               ::=   число | имя | имя ([выражение[,выражение]...]) |

- терм | (выражение)

имя                 ::= буква [буква|цифра]...

число              ::= цифра …

буква              ::=  A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z

   a|b|c|d|e|f |g|h|i|j|y|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z

цифра             ::=   0|1|2|3|4|5|6|7|8|9

 

     Эта грамматика описывает  синтаксис и лексику языка  СО. К лексике относятся четыре  последних правила.

 

    1. Использование компилятора С0

 

Для трансляции и выполнения С0-программы используется следующая последовательность команд MS DOS:

с0.exe        трансляция

masm p.asm       ассемблирование

tlink p.obj       компоновка

p.exe [<входной_файл] [>выходной_файл]  выполнение

 

Компилятор С0 вводит исходную программу из файла p.c0, помещая результат трансляции на языке ассемблера в файл p.asm. Затем производятся ассемблирование, компоновка (редактирование связей) и выполнение программы. Объектный и исполняемый модули транслируемой программы обычно получаются в файлах p.asm и p.exe.

 

 

 

 

 

 

 

    1. Сообщения об ошибках

 

Сообщения об ошибках в исходной программе также вставляются компилятором С0 в объектный код в виде строк комментария, содержащего номер (тип) ошибки и символ “^”, указывающий на текущую позицию предшествующей исходной строки в момент обнаружения ошибки. В конце объектной программы вставляется итоговое сообщение о количестве обнаруженных ошибок, дублируемое на экране.

Далее приведён перечень сообщений об ошибках (номер указывает на номер (тип)  ошибки):

 

1. Число больше 32767

2. Слишком много имен

3. Требуется int или имя функции

4. Многократно описанное имя

5. Требуется '('

6. Требуется имя

7. Требуется ')'

8. Не удалось открыть входной  или выходной файл

9. Недопустимый символ

10. Требуется ','

11. Требуется '{'

12. Требуется ';'

13. Требуется '}'

14. Имя не описано

15. Неверный ограничитель в выpажении

16. Неверный тип операнда выражения

17. Несоответствующие типы операндов

18. Неверный тип левого операнда  пpисваивания

19. Нет имени функции

20. Неверный вызов функции

21. Деление на ноль

 

В процессе расширения функционала была добавлена ошибка 23. Унарная операция. 

  1. ОПИСАНИЕ ПРОГРАММЫ
    1. Описание новых возможностей языка С0
      1. Тип данных char

Вводим перечисление типов данных

enum typ_t {

int_t,char_t

};

 

Добавляем соответствующее поле в структуру таблицы имен

struct eltabim    /* элемент таблицы имен:                   */

{  char imja[9];  /* имя (байты: 0..8 - имя и 0)             */

   short vidob;   /* вид об'екта:1 - пеpеменная, 3 - фyнкция */

   short smesch;  /* смещение в области локальных данных     */

   typ_t typ;     /* тип переменной                          */

};

 

Добавляем структуру str_tip которая описывает переменную C0:

struct sz_typ {

typ_t typ;

int value;

};

 

Изменим тип данных sz на struct strtype:

sz_typ sz[20];

 

      Добавляем тип лексемы:

enum  tipleks {                  /* тип лексемы:             */

  osh,  ident,  chislo,  plus,  minus,  umn,  del,  ost,  ravn,  neravn,

  men,  bol,  mravn,  bravn,  lskob,  pskob,  zpt,  tchzpt,  prisv,  flskob,

  fpskob, ifsl, else,  intsl,  retsl,  whilesl,  charsl};

 

Изменим таблицу служебных слов и добавим типы лексем для служебных слов:

char *tabsl[10]=                  /* таблица служебных слов   */

                  {"" ,"if", "int", "return", "while", "char","for","to","downto","do"};

enum tipleks tipsl[10]={ ident,ifsl,intsl,retsl,whilesl,charsl,forsl,tosl,downtosl,dosl};

 

Добавим функцию opisper_char для описания переменных:

 

void opisper_char(int t) /* допустимый индекс таблицы для дублиpования имен */

{ 

int i;

chleks();

while (leksema == ident) {

i = pozic(kolim);    /* позиция имени в таблице имен */

if (i > t) oshibka(4); /* нашли - дублиpование имен */

else {

i = vkluch();        /* включить имя в таблицу */

tabim[i].typ = char_t;

tabim[i].vidob = 1;  /* вид объекта - пеpем-я  */

}

chleks();

if (leksema != tchzpt) {

if (leksema != zpt) oshibka(10); /* тpебуется ','*/

if (leksema != ident) chleks();

}

}

if (leksema != tchzpt) oshibka(12);  /* тpебуется ';'*/

}

 

В функции main

else if (leksema == charsl) {              /* слово int        */

opisper_char(0);

kolglb=kolim;

 

Далее, необходимо провести изменения, связанные с оператором присваивания для типов char и int:

else { /*     компилиpовать опеpацию      */

if (z1->typ == int_t && z2.typ == char_t && *t1 != 0) {

zopreg(z2,t2,"AL");

fprintf(fvih,"\tCBW\n");

fprintf(fvih,"\tPUSH\tAX\n");

t2 = 4;

z2.typ = int_t;

} 

 

 

      1. Операции ++,--

void operac(int *z1, int *t1, enum tipleks op, int z2, int t2)

else if (op==uvel || op==umen) /* ++ или -- */

   {  op==uvel? strcpy(kop,"INC") : strcpy(kop,"DEC") ;

      if (*t1 == 0) /*нет 1-го операнда: префиксная оп-ция */

         if(t2==3 && tabim[z2].vidob==1) /*2-й оп-д - пер-я*/

         {  fprintf(fvih,"\t%s\t%s\n",kop,adrper(z2));

            zopreg(z2,t2,"AX");

         }

         else oshibka(16);      /* неверный тип операнда */

      else

         if(t2==0&&*t1==3&&tabim[*z1].vidob==1)/*имя++|имя--*/

         {  zopreg(*z1,*t1,"AX");

            fprintf(fvih,"\t%s\t%s\n",kop,adrper(*z1));

         }

         else oshibka(16);      /* неверный тип операнда */

  } 

 

 

enum tipleks chleks()

else  

if (*usim=='+' || *usim=='-') /* + или - или ++ или -- */

{ 

c=*usim;

(chsim() == c)        /* ++ или -- */

{ 

if (c == '+')   leksema=uvel;        /* ++ */

else            leksema=umen;        /* -- */

chsim();   /* чтение символа след. лексемы */

}

else

leksema=leksim[c];    /* + или - */

}

 

      1. Оператор if else

char *tabsl[6]=                  /* таблица служебных слов   */

                {   "" ,"if", "int", "return", "while", "do" };

enum tipleks tipsl[6]={ ident,ifsl,  intsl,  retsl,   whilesl,dosl};

long int st2[28]=            /* st2[i]=2**i (i=0..26)    */

      {1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,

      32768,65536,131072,262144,524288,1048576,2097152,4194304,

       8388608,16777216,33554432,67108864,134217728};

 

noper=st2[flskob]|st2[ifsl]|st2[whilesl]|st2[retsl]|st2[dosl]|

         st2[tchzpt]|nvir;   /* мн-во начальных лексем оп-pа */

 

        /**********************************************/

        /*           тpансляция опеpатоpа             */

        /**********************************************/

   void operatr(long mlvoz)   /* множ-во лексем возобн-я анализа */

else if (leksema==ifsl)         /* IF - условный опеpатоp */

   {

   tipop=1;

   chleks();

   if (leksema==lskob)

   { 

   virag(st2[pskob]|noper|mlvoz);  /* выpажение-условие */

   nmet=++kmet;                 /* # метки ССi */

   gen_kom("","POP","AX");

   gen_kom("","TEST","AX,AX");

   sprintf(top,"CC_%d", nmet);  gen_kom("","JNZ",top);

   sprintf(top,"CC_%d",++kmet); gen_kom("","JMP",top);

   sprintf(top,"CC_%d:",nmet);  gen_kom(top,"","");

   }

   else 

   oshibka(5);                  /* тpебуется  (      */

   operatr(mlvoz);

   sprintf(top,"CC_%d:",nmet+1);  gen_kom(top,"","");

   }

 

      1. Комментарий: \\

 

Изменения исходного кода компилятора: для реализации данного типа комментария достаточно внести изменения в функции chleks:

 

        /**********************************************/

        /*               чтение лексемы               */

        /**********************************************/

   enum tipleks chleks()

 

 

else  /*           односимвольная лексема                  */

{

leksema = leksim[*usim];

if (*usim == '/')

{

chsim();

if (*usim == '/')

{

do

{

chsim(); // пропускаем символы

}

while (*usim != 10 && *usim != 13);

chsim(); 

leksema = chleks();

}

}

else

{

           chsim();

      }

}

return leksema;

}

 

 

3.1.5. Константа 16-ная.

 

        /**********************************************/

        /*               чтение лексемы               */

        /**********************************************/

enum tipleks chleks()

{

.

.

.

.

else

if (*usim >= '0' && *usim <= '9')

{  

/* цифра */

/*           чтение числа            */

znach = 0;

leksema = chislo;

if (*usim == '0')

{

chsim();

if (*usim == 'X' || *usim == 'x')

{

mn = 16;

chsim();

}

}

while (*usim >= '0' && *usim <= '9' || mn == 16 &&

(*usim >= 'A' && *usim <= 'F' || *usim >= 'a' && *usim <= 'f'))

{

if (znach > 32767)

{

oshibka(1);

znach = 0;

/*пpопуск цифp*/

while (chsim() >= '0' && *usim <= '9' || mn == 16 &&

(*usim >= 'A' && *usim <= 'F' || *usim >= 'a' && *usim <= 'f'));

}

else

{

if (*usim >= '0' && *usim <= '9')

{

znach = mn * znach + *usim - '0';

chsim();

}

else

{

if (*usim >= 'a' && *usim <= 'f') *usim = *usim - 'a' + 'A';

if (*usim >= 'A' && *usim <= 'F' && mn == 16)

{

znach = mn * znach + *usim - 'A' + 10;

chsim();

}

else

{

oshibka(23);

znach = 0;

/*пpопуск цифp*/

while (chsim() >= '0' && *usim <= '9' || mn == 16 &&

(*usim >= 'A' && *usim <= 'F' || *usim >= 'a' && *usim <= 'f'));

}

}

}

}

 

3.2. Список подпрограмм  транслятора С0

Список подпрограмм транслятора С0 представлен в таблице 1.

Таблица 1

Номер

строки

Имя

Назначение

Вызываемые

функции

816

 

 

924

 

1106

 

136

 

 

 

584

 

382

 

 

 

217

 

 

243

 

 

269

 

991

 

369

 

 

950

 

977

 

 

465

 

 

 

768

 

 

959

 

796

chleks

 

 

chsim

 

kodret

 

main

 

 

 

operac

 

operatr

 

 

 

opisper_int

 

 

opisper_ptr

 

 

oprfun

 

oshibka

 

poslop

 

 

pozic

 

test

 

 

virag

 

 

 

vitsk

 

 

vkluch

 

zopreg(z,t,r)

 

Чтение очередной лексемы и присваива ние её значения переменной leksema.

 

Чтение символа.

 

Генерация кода оператора return.

 

Трансляция конструкции «программа».

 

 

 

Компиляция/интерпретация операции выражения.

 

Трансляция конструкции оператор.

 

 

 

Трансляция конструкции «описание переменных» для типа int.

 

Трансляция конструкции «описание переменных» для типа ptr

 

Трансляция конструкции «описание функции».

 

Генерация сообщения о типе и позиции ошибки.

 

Трансляция последовательности операторов вида “[оператор]…}”.

 

Поиск позиции имени в таблице имён.

 

Проверка лексемы. В случае ошибки – выдача сообщения и пропуск части тела программы.

 

Трансляция выражения (определение порядка операций).

 

 

Выталкивание из стека скобки “(“ или “имя(“.

 

 

Включение имени в таблицу имён.

 

Генерация кода загрузки в регистр r операнда z типа t.

chsim.

 

 

—

 

—

 

opisper_int,

opisper_ptr,

test,oprfun.

 

oshibka.

 

virag,chleks,

poslop,

operator,oshibka,

kodret,test.

pozic, oshibka

vkluch,chleks.

 

pozic, oshibka

vkluch,chleks.

 

opisper, pozic, oshibka

vkluch,chleks.

 

operator,chleks,

test.

 

—

 

oshibka

chleks.

 

chleks,pozic,vkluch,

oshibka, operac,vitsk

zopreg,test

 

zopreg, ,

oshibka.

 

oshibka.

 

adrper,oshibka

.


 

 

4. ТЕСТИРОВАНИЕ ПРОГРАММЫ

 

Для тестирования новых возможностей языка C0 на вход транслятора подавалась следующая программа на языке С0:

 

int g,h,f;

main ()

{

 

   g=0xC8;

   f=g;

   f++;//primer so skobkoi

   putn(f);

   putchar(10);

   putchar(13);

   if (f>200)

   {

     do

     {

       h=g--; 

       putn(h);

       putchar(10);

       putchar(13);

     }

     while(h!=190);

   }  

   getch();

}

На выходе сформировался файл p.asm следующего содержания:

ASSUME CS:KOM_,SS:STEK_,DS:DAN_

STEK_ SEGMENT STACK

DW 10000 DUP (?)

DNOST_ DW ?

STEK_ ENDS 

;int g,h,f;

;main ()

KOM_ SEGMENT 

_main PROC FAR

MOV AX,DAN_

MOV DS,AX

MOV AX,STEK_

MOV SS,AX

;{

;

;   g=0xC8;

LEA SP,DNOST_

PUSH BP

MOV BP,SP

MOV AX,200

;   f=g;

MOV _g,AX

MOV AX,_g

;   f++;//primer so skobkoi

MOV _f,AX

INC _f

;   putn(f);

MOV AX,_f

MOV AX,_f

PUSH AX

;   putchar(10);

CALL _putn

MOV AX,10

PUSH AX

;   putchar(13);

CALL _putchar

MOV AX,13

PUSH AX

;   if (f>200)

CALL _putchar

MOV BX,200

MOV AX,_f

CMP AX,BX

MOV AX,1

JG CC_1

SUB AX,AX

CC_1:  

;   {

TEST AX,AX

JNZ CC_2

JMP CC_3

;     do

CC_2:  

;     {

;       h=g--; 

CC_4:  

DEC _g

MOV AX,_g

;       putn(h);

MOV _h,AX

MOV AX,_h

PUSH AX

;       putchar(10);

CALL _putn

MOV AX,10

PUSH AX

;       putchar(13);

CALL _putchar

MOV AX,13

PUSH AX

;     }

;     while(h!=190);

CALL _putchar

MOV BX,190

MOV AX,_h

CMP AX,BX

MOV AX,1

JNE CC_5

SUB AX,AX

CC_5:  

TEST AX,AX

;   }  

JNZ CC_4

;   getch();

CC_3:  

;}

CALL _getch

POP BP

MOV AH,4CH

INT 21H

;

_main ENDP 

INCLUDE std.asm

KOM_ ENDS 

DAN_ SEGMENT 

_g DW ?

_h DW ?

_f DW ?

DAN_ ENDS 

END _main

;Компилятоp С0 от 10/04/08:

;колич. ошибок 0

 

В результате ассемблирования, компоновки и выполнения данной программы на экране сформировался следующий результат:

C:\DOCUME~1\9335~1\C316~1\GOOGLE~1\__8EC9~1\ALINA~1\TEST_A~1>p

201

199

198

197

196

195

194

193

192

191

190 
ЗАКЛЮЧЕНИЕ

 

В результате выполнения данной курсовой работы были более подробно рассмотрены методы трансляции, а также произведено самостоятельное расширение возможностей транслятора.

 

 

 

СПИСОК ЛИТЕРАТУРЫ

 

  1. Хохлов Д.Г.  Основы технологии модульного программирования:  Учебное пособие.-Казань:  КГТУ (КАИ), 2003.—62 с.
  2. Хохлов Д.Г.  Системное программное обеспечение: Учебное пособие.-Казань:  КГТУ (КАИ), 2006.—135 с.