Виконав:
студент групи АП-30б
Шпіка П. М.
Перевірив:
Межерицький С. Г.
1. Тема роботи: Інтерпретатори.
2. Мета роботи: Освоїти принципи написання інтерпретаторів на прикладі написання програми, що виконує команди і директиви язика асемблера процесора 8086.
3. Постановка задачі: Необхідно розробити програму, що виконує команди язика асемблер.
4. Розробка алгоритму рішення задачі:
4.1. Вибір перемінних.
Тут розглядаються тільки основні перемінні, котрі є найбільш основними для даної програми. Імена перемінних, їхній тип і функціональне призначення приведені в таблиці 1.
Таблиця 1.
ім'я |
тип |
призначення |
*mnemonics[] *registers[] opcode op1num op2num regval [sizeof(registers/ sizeof(char *)] |
char char int int int int |
Покажчик на елемент масиву mnemonics. Цей масив містить найменування команд язика асемблера, що зустрічаються у вихідному тексті. --//-- Індекс для масиву mnemonics. --//-- registers --//-- registers Масив вмістів імітованих регістрів. |
4.2. Опис структури програми:
Імена функцій, їхній тип і призначення приведені в таблиці 2.
Таблиця 2.
ім'я |
тип |
Призначення |
Strtoi Strupcase Strcomp *parse findstr push pop execcmd main |
int void char char int void int void void |
Порівняння виділеної лексеми з десятковим числом. У випадку позитивного результату повертає значення 0. Перетворення рядкових символів у прописні. Порівняння двох рядків. Виділення лексеми з рядка. Пошук рядка в масиві рядків. У випадку присутності повертає її індекс у масиві, у противному випадку: -1. Імітація занесення в стек. Імітація узяття зі стека. Виконання команд. Головна програма. |
Загальний алгоритм рішення задачі такий:
1) Вводиться з клавіатури команда (рядок).
2) Якщо рядок порожній, то вихід із програми.
3) Виробляється синтаксичний аналіз введеного рядка.
4) Якщо немає помилок, команда виконується, у противному випадку – перехід до пункту 1.
5. Текст програми interp.c:
#include <stdio.h>
#define PT_EOST 0
#define PT_SIGN 1
#define PT_WORD 2
#define INUL ((int *) 0)
#define MAXSTR 64
#define STACKLEN 16
#define OP_MOV 0
#define OP_DEC 1
#define OP_INC 2
#define OP_ADD 3
#define OP_SUB 4
#define OP_PUSH 5
#define OP_POP 6
#define OP_RET 7
#define OP_OR 8
#define OP_XOR 9
#define OP_AND 10
#define OP_NOT 11
char *registers[] = {
"AX",
"BX",
"CX",
"DX",
"SP",
#define RSP 4
"BP",
"SI",
"DI",
"IP",
#define RIP 8
"IMM"
#define RIMM 9
};
char *mnemonics[] = {
"MOV",
"DEC",
"INC",
"ADD",
"SUB",
"PUSH",
"POP",
"RET",
"OR",
"XOR",
"AND",
"NOT"
""
};
char operandcount[] = {2, 1, 1, 2, 2, 1, 1, 0, 2, 2,2,1};
char signs[] = "~!@#$%^&*()_)+|`\\=,./<>?;':\"";
char separators[] = "\t \r\n";
int regval[sizeof(registers) / sizeof(char *)];
char parsetyp = 0;
int stack[STACKLEN];
char pswz = 0;
char lexbuf[MAXSTR];
char cmdbuf[MAXSTR];
int strtoi(char *s, int *i)
{
int sign;
int val;
val = 0;
if(!*s)
return -1;
if(*s == '-')
{
sign = -1;
s++;
}
else
sign = 1;
while(*s)
{
if(*s < '0') return -1;
if(*s > '9') return -1;
val *= 10;
val += *s - '0';
*s++;
}
*i = val * sign;
return 0;
}
void push(int it)
{
if(((unsigned) regval[RSP]) > STACKLEN)
{
printf("Invalid SP value. Stack pointer is adjusted\n");
regval[RSP] = 0;
}
stack[regval[RSP]] = it;
}
int pop(void)
{
if(((unsigned) regval[RSP]) > STACKLEN)
{
printf("Invalid SP value. Stack pointer is adjusted\n");
regval[RSP] = 0;
}
return stack[--regval[RSP]];
}
void strupcase(char *s)
{
while(*s)
{
if((*s > ('a' - 1)) && (*s < ('z'+1)))
*s -= ('z' - 'Z');
s++;
}
}
char strcomp(char *s1, char *s2)
{
while(*s1)
{
if(*s1 != *s2)
return 0;
s1++;
s2++;
}
if(*s2)
return 0;
return 1;
}
void execcmd(char code, int *op1, int *op2)
{
switch (code)
{
case OP_MOV : *op1 = *op2; break;
case OP_DEC : (*op1)--; pswz = (*op1 == 0); break;
case OP_INC : (*op1)++; pswz = (*op1 == 0); break;
case OP_ADD : *op1 += *op2; pswz = (*op1 == 0); break;
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.