Системное программное обеспечение. 2
Казанский государственный научно исследовательский технический университет им. А.Н.Туполева
Кафедра АСОИУ
Курсовая работа
по дисциплине
"Системное программное обеспечение"
Выполнила:
гр.4452
Руководитель:
Казань 2013
СОДЕРЖАНИЕ
3.1.1 Тип данных: char………………………………………..… 3.1.2 Дополнительные операции: ++,--……………………... 3.1.3 if else………………………………………………… 3.1.4 Тип комментария: \\………………………………………... 3.1.5 Тип констант: 16……………………………………………
|
3 3 3 3 4 5 6 5 5 6 12 14 15 17 21 22 23 |
- ЗАДАНИЕ
Расширить язык и транслятор С0, реализовав в них следующие возможности:
- Тип данных: char
- Тип констант: 16;
- Операции: ++,--;
- Оператор if else;
- Комментарий: \\
- ОПИСАНИЕ ПРИМЕНЕНИЯ
- Общие сведения о трансляторе С0
Транслятор С0 переводит исходную программу с языка С0 на язык ассемблера IBM PC. Таким образом, использование языка ассемблера в качестве объектного языка делает его однопроходным и более удобным в понимании основных методов трансляции, избежав многочисленных деталей генерации машинного кода.
Транслятор написан на языке С и состоит из 18 подпрограмм, которые используют около 30 глобальных переменных.
Трансляция выражений в С0 производиться методом стека с приоритетом. Остальные конструкции языка (операторы и описания) транслируются методом рекурсивного спуска.
- Возможности языка С0
Входной язык С0 является подмножеством языка С и содержит данные только целочисленного типа, без массивов. Разрешаются глобальные и локальные переменные, функции с параметрами, рекурсия.
Параметры функции могут быть только входными, поэтому результат работы функции передается только в виде ее значения или присваивается глобальной переменной. Параметры не описываются.
Имеются следующие операторы: оператор-выражение, составной оператор, сокращённый условный оператор, цикл с предусловием, оператор возврата.
В выражениях допускаются:
- арифметические операции: +, -, *, /, %;
- сравнения: ==, !=, <, >, <=, >=;
- присваивание: =;
- скобки: ( ).
Отсутствующие в языке С0 логические операции И и ИЛИ можно заменить * или + соответственно.
Примечания.
- Служебные слова пишутся строчными буквами.
- Длина имени не ограничена, но учитываются не более 8 символов.
- Отсутствующий оператор return в конце описания функции вставляется автоматически.
Грамматика языка СО.
программа ::= {описание-переменных [ описание-функции}...
описание-переменных ::= int имя [,имя]...;
описание-функции ::= имя ( [имя[,имя]...] )
{ [описание-переменных]...[
оператор ::= [выражение]; | { [оператор]... } |
if (выражение) оператор | return [выражение];
while (выражение) оператор
выражение ::= терм [{+|-|*|/|%|<|>|<=|>=|==|!=|=}
терм ::= число | имя | имя ([выражение[,выражение]...]) |
- терм | (выражение)
имя ::= буква [буква|цифра]...
число ::= цифра …
буква
::= A|B|C|D|E|F|G|H|I|J|K|L|M|N|
a|b|c|d|e|f |g|h|i|j|y|k|l|m|n|o|p|q|r|s|
цифра ::= 0|1|2|3|4|5|6|7|8|9
Эта грамматика описывает синтаксис и лексику языка СО. К лексике относятся четыре последних правила.
- Использование компилятора С0
Для трансляции и выполнения С0-программы используется следующая последовательность команд MS DOS:
с0.exe трансляция
masm p.asm ассемблирование
tlink p.obj компоновка
p.exe [<входной_файл] [>выходной_файл] выполнение
Компилятор С0 вводит исходную программу из файла p.c0, помещая результат трансляции на языке ассемблера в файл p.asm. Затем производятся ассемблирование, компоновка (редактирование связей) и выполнение программы. Объектный и исполняемый модули транслируемой программы обычно получаются в файлах p.asm и p.exe.
- Сообщения об ошибках
Сообщения об ошибках в исходной программе также вставляются компилятором С0 в объектный код в виде строк комментария, содержащего номер (тип) ошибки и символ “^”, указывающий на текущую позицию предшествующей исходной строки в момент обнаружения ошибки. В конце объектной программы вставляется итоговое сообщение о количестве обнаруженных ошибок, дублируемое на экране.
Далее приведён перечень сообщений об ошибках (номер указывает на номер (тип) ошибки):
1. Число больше 32767
2. Слишком много имен
3. Требуется int или имя функции
4. Многократно описанное имя
5. Требуется '('
6. Требуется имя
7. Требуется ')'
8. Не удалось открыть входной или выходной файл
9. Недопустимый символ
10. Требуется ','
11. Требуется '{'
12. Требуется ';'
13. Требуется '}'
14. Имя не описано
15. Неверный ограничитель в
16. Неверный тип операнда
17. Несоответствующие типы
18. Неверный тип левого операнда пpисваивания
19. Нет имени функции
20. Неверный вызов функции
21. Деление на ноль
В процессе расширения функционала была добавлена ошибка
23. Унарная операция.
- ОПИСАНИЕ ПРОГРАММЫ
- Описание новых возможностей языка С0
- Тип данных 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","
enum tipleks tipsl[10]={ ident,ifsl,intsl,retsl,
Добавим функцию 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;
}
- Операции ++,--
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,
zopreg(z2,t2,"AX");
}
else oshibka(16); /* неверный тип операнда */
else
if(t2==0&&*t1==3&&tabim[*z1].
{ zopreg(*z1,*t1,"AX");
fprintf(fvih,"\t%s\t%s\n",kop,
}
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]; /* + или - */
}
- Оператор 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,
32768,65536,131072,262144,
8388608,16777216,33554432,
noper=st2[flskob]|st2[ifsl]|
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);
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,"","");
}
- Комментарий: \\
Изменения исходного кода компилятора: для реализации данного типа комментария достаточно внести изменения в функции 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:
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\
201
199
198
197
196
195
194
193
192
191
190
ЗАКЛЮЧЕНИЕ
В результате выполнения данной курсовой работы были более подробно рассмотрены методы трансляции, а также произведено самостоятельное расширение возможностей транслятора.
СПИСОК ЛИТЕРАТУРЫ
- Хохлов Д.Г. Основы технологии модульного программирования: Учебное пособие.-Казань: КГТУ (КАИ), 2003.—62 с.
- Хохлов Д.Г. Системное программное обеспечение: Учебное пособие.-Казань: КГТУ (КАИ), 2006.—135 с.