Разработка однопроходного компилятора

Задачи трансляторов, характеристика их видов. Этапы и функции основных фаз процесса компиляции. Описание используемых директив и команд ассемблера, алгоритмов, таблиц. Листинг программы. Алгоритм работы программной реализации разрабатываемого компилятора.

Рубрика Программирование, компьютеры и кибернетика
Вид курсовая работа
Язык русский
Дата добавления 24.06.2013
Размер файла 1,3 M

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

Размещено на http://www.allbest.ru/

Оглавление

Введение

Расчёт варианта задания

Разработка контрольного примера

Описание используемых директив и команд ассемблера

Выбор варианта построения ассемблера, описание алгоритмов и таблиц

Листинг программы

Алгоритм работы программной реализации разрабатываемого компилятора

Заключение

Введение

Основной целью курсовой работы является создание и изучение объектного файла. Создаваемый объектный файл должен восприниматься линковщиком и преобразовываться в исполняемый файл (COM или EXE). Перевод исходной программы в её объектное представление осуществляет транслятор, поэтому его программная реализация также является целью курсовой работы.

Транслятор - это программа, которая переводит входную программу на исходном (входном) языке в эквивалентную ей выходную программу на результирующем (выходном) языке.

С точки зрения принципа работы транслятор выступает как переводчик: преобразует предложения входного языка в эквивалентные им предложения выходного языка. Кроме того, само слово «транслятор» означает «переводчик».

Транслятор обычно выполняет также диагностику ошибок, формирует словари идентификаторов, выдаёт для печати тексты программы и т. д.

Язык, на котором представлена входная программа, называется исходным языком, а сама программа - исходным кодом. Выходной язык называется целевым языком или объектным кодом.

Трансляторы подразделяют:

• Диалоговый. Обеспечивает использование языка программирования в режиме разделения времени.

• Синтаксически-ориентированный (синтаксически-управляемый). Получает на вход описание синтаксиса и семантики языка и текст на описанном языке, который и транслируется в соответствии с заданным описанием.

• Однопроходной. Формирует объектный модуль за один последовательный просмотр исходной программы.

• Многопроходной. Формирует объектный модуль за несколько просмотров исходной программы.

• Оптимизирующий. Выполняет оптимизацию кода в создаваемом объектном модуле.

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

• Обратный. Для программы в машинном коде выдаёт эквивалентную программу на каком-либо языке программирования.

Процесс компиляции состоит из двух основных этапов ? анализа и синтеза (рис. 1).

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

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

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

Лексический анализ. Эту часть компилятора выполняет сканер, который читает литеры программы (символы) на исходном языке и строит из них слова (лексемы) исходного языка. На входе сканера (лексического анализатора) текст исходной программы, выходная информация передаётся для дальнейшей обработки на этап синтаксического разбора.

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

Рис. 1. Функции основных фаз компиляции:

Семантический анализ ? это часть компилятора, проверяющая часть текста исходной программы с точки зрения семантики входного языка.

Подготовка к генерации кода ? на этой фазе компилятор выполняет предварительные действия, непосредственно связанные с синтезом текста результирующей программы: идентификация элементов языка, распределение памяти и т.п. Эта подготовка ещё не ведёт к порождению текста на выходном языке.

Генерация кода ? это фаза, на которой непосредственно порождаются команды, составляющие предложения выходного языка и текст результирующей программы в целом. Фаза генерации кода основная на этапе синтеза результирующей программы. Кроме этого, генерация обычно включает в себя и оптимизацию. Оптимизация ? это процесс, связанный с обработкой уже порождённого текста и оказывающий существенное влияние на качество и эффективность результирующей программы.

Таблицы идентификаторов - это специальным образом организованные наборы данных, которые хранят информацию об элементах исходной программы. Содержимое таблицы идентификаторов используется для порождения текста результирующей программы. В процессе компиляции нужно хранить информацию о переменных, константах, функциях и т.п. Конкретный состав таблицы идентификаторов зависит от используемого входного языка программирования.

Достоинство компилятора: программа компилируется один раз и при каждом выполнении не требуется дополнительных преобразований. Соответственно, не требуется наличие компилятора на целевой машине, для которой компилируется программа. Недостаток: отдельный этап компиляции замедляет написание и отладку и затрудняет исполнение небольших, несложных или разовых программ.

В случае если исходный язык является языком ассемблера (низкоуровневым языком, близким к машинному языку), то компилятор такого языка называется ассемблером.

Другой метод реализации - когда программа исполняется с помощью интерпретатора вообще без трансляции. Интерпретатор программно моделирует машину, цикл выборки-исполнения которой работает с командами на языках высокого уровня, а не с машинными командами. Такое программное моделирование создаёт виртуальную машину, реализующую язык. Этот подход называется чистой интерпретацией. Чистая интерпретация применяется как правило для языков с простой структурой (например, АПЛ или Лисп). Интерпретаторы командной строки обрабатывают команды в скриптах в UNIX или в пакетных файлах (.bat) в MS-DOS также как правило, в режиме чистой интерпретации.

Достоинство чистого интерпретатора: отсутствие промежуточных действий для трансляции упрощает реализацию интерпретатора и делает его удобнее в использовании, в том числе в диалоговом режиме. Недостаток - интерпретатор должен быть в наличии на целевой машине, где должна исполняться программа. А свойство чистого интерпретатора, что ошибки в интерпретируемой программе обнаруживаются только при попытке выполнения команды (или строки) с ошибкой, можно признать как недостатком, так и достоинством.

Существуют компромиссные между компиляцией и чистой интерпретацией варианты реализации языков программирования, когда интерпретатор перед исполнением программы транслирует её на промежуточный язык (например, в байт-код или p-код), более удобный для интерпретации (то есть речь идёт об интерпретаторе со встроенным транслятором). Такой метод называется смешанной реализацией. Примером смешанной реализации языка может служить Perl. Этот подход сочетает как достоинства компилятора и интерпретатора (большая скорость исполнения и удобство использования), так и недостатки (для трансляции и хранения программы на промежуточном языке требуются дополнительные ресурсы; для исполнения программы на целевой машине должен быть представлен интерпретатор). Также, как и в случае компилятора, смешанная реализация требует, чтобы перед исполнением исходный код не содержал ошибок (лексических, синтаксических и семантических).

По мере увеличения ресурсов компьютеров и расширения гетерогенных сетей (в том числе Интернета), связывающих компьютеры разных типов и архитектур, выделился новый вид интерпретации, при котором исходный (или промежуточный) код компилируется в машинный код непосредственно во время исполнения, «на лету». Уже скомпилированные участки кода кэшируются, чтобы при повторном обращении к ним они сразу получали управление, без перекомпиляции. Этот подход получил название динамической компиляции.

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

Этот метод хорошо подходит для веб-приложений. Соответственно, динамическая компиляция появилась и поддерживается в той или иной мере в реализациях Java,.NET Framework, Perl, Python.

Расчёт варианта задания

Расчёт задания для каждой группы команд идёт по формуле:

(1)

Где: NG - последние две цифры учебной группы студента, NS - номер студента в списке группы, KV - количество вариантов в соответствующей группе команд.

Тогда, получаем:

· ((83+9) mod 12) = 8;

· ((83+9) mod 15) = 2;

· ((83+9) mod 10) = 2;

· ((83+9) mod 8) = 4;

· ((83+9) mod 6) = 2.

В результате базовый набор команд: NOP, JG, ADD, ROR, DEC. Так же нам понадобятся команды MOV, INT.

Разработка контрольного примера

.286

datasegment

a1dw 1001h

a2 dw 100h

a3 dw 101h

c dw 4c00h

data ends

code segment

assume ds:data, cs:code

main:

mov ax,a1

add ax,101h

dec a3

ror ax,5h

jg @2

nop

@2:

mov ax,c

int 21h

code ends

end main

Данный контрольный пример без ошибок компилируется и линкуется стандартными компиляторами и линковщиками.

Описание используемых директив и команд ассемблера

транслятор ассемблер компилятор

- r8, r16, r32 - операнд в одном из регистров размером байт, слово или двойное слово;

- m8, m16, m32 - операнд в памяти размером байт, слово или двойное слово;

- i8, i16, i32 - непосредственный операнд размером байт, слово или двойное слово;

- a8, a16, a32 - относительный адрес (смещение) в сегменте кода;

Выбор варианта построения ассемблера, описание алгоритмов и таблиц

MOV:

Пересылает один байт или одно слово между регистрами или между регистром и памятью, а также передаёт непосредственное значение в регистр или в память. Команда MOV не может передавать данные между двумя адресами памяти (для этой цели служит команда MOVS).

ADD:

DEC:

ROR:

JG:

NOP:

INT:

Листинг программы

unit Unit1;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, StdCtrls, Grids, ExtCtrls, ComCtrls, Menus,math;

type

Directive = record //запись - директива

part1:string;

part2:string;

part3:string;

MashCode:string;

exist:boolean; //признак того, что директива описана и распознаётся

end;

Command = record //запись - оператор

mark:string;

oper:string;

arg1:string;

arg2:string;

MashCode:string;

ByteLen:string;

exist:boolean; //признак того что оператор описан и распознаётся

end;

Prog = record

isCodeSeg:boolean; //наличие сегмента кода

isDataSeg:boolean; //наличие сегмента данных

end;

TForm1 = class(TForm)

PageControl1: TPageControl;

TabSheet1: TTabSheet;

TabSheet2: TTabSheet;

Label4: TLabel;

Code: TMemo;

marks: TStringGrid;

Title: TMemo;

CodeSeg: TMemo;

DataSeg: TMemo;

EndFile: TMemo;

MainMenu1: TMainMenu;

Program1: TMenuItem;

Exit1: TMenuItem;

exeAll: TButton;

CreateObjFile: TButton;

Varibles: TStringGrid;

ScrollBar1: TScrollBar;

DataSourceSeg: TMemo;

Label5: TLabel;

Label6: TLabel;

Label7: TLabel;

Label8: TLabel;

Label9: TLabel;

Label10: TLabel;

Label11: TLabel;

markslinks: TStringGrid;

GroupBox1: TGroupBox;

ComBytePosMemo: TMemo;

MashCode: TMemo;

Label1: TLabel;

Label3: TLabel;

SaveMenu: TMenuItem;

ClearCodeButton: TButton;

Edit1: TEdit;

TranslAndSaveMenu: TMenuItem;

NewProgramButton: TButton;

OpenDialog1: TOpenDialog;

Memo1: TMemo;

SaveDialog1: TSaveDialog;

procedure NewProgramButtonClick(Sender: TObject); //Подготовка к работе

procedure TranslAndSaveMenuClick(Sender: TObject);//Моментальная трансляция

procedure ClearCodeButtonClick(Sender: TObject);//Очистка кода

procedure CreateObjFileClick(Sender: TObject);//Вычисление сегментов данных

procedure exeAllClick(Sender: TObject);//Трансляция кода

procedure Exit1Click(Sender: TObject);//Закрыть приложение

procedure FormCreate(Sender: TObject);

//Проверки

function GerArgType(arg:string):string;//получение типа аргумента

function IsVar(arg:string):boolean;//переменная

function isImm(arg:string):boolean; //число

function isData(str:string):boolean;//[si+n]

function isReg(arg:string):boolean; //регистр 16

//рассчет мнемокода

function insRegMul(mem:string; arg:string; koef:integer):string;

function insReg(mem:string; arg:string):string;

function InvertBytes(s:string):string;

function ImmToHex(imm:string;len:string):string;

function cnvData(dat:string):string;

function AddControlByte(s:string):string;

function HexByteToByte(s:string):byte;

function CharToByte(C:char):byte;

function NexStrToStr(nexstr:string):string;

function IntToHexStr(int:integer):string;

function AnalysisCommand (comstr:string):command;

function ComNext:string;

function ComRead:string;

function ComIs:string;

function DeleteSpace(str:string):string;

function DecompositeCommand(comstr:string):Command;

function ModifyMarkAdress:string;

procedure AddLinksInMarkers;

procedure MarkTableWrite(Mname,LBytepos,CBytepos,Strpos:string);

procedure MarksLinksTableWrite(Mname,LBytepos:string);

procedure ComExe;

function AnalysisDirective(DrcStr:string):directive;

function DecompositeDirective(DrcStr:string):directive;

procedure DataTableWrite(Varible:string; Len:string;Code:string);

function GetVarCodeByName(name:string):string;

//управление прокруткой

procedure SlideDown;

procedure SlideUp;

procedure ScrollBar1Change(Sender: TObject);

//Загрузка и сохранение

procedure CodeDblClick(Sender: TObject);

procedure SaveMenuClick(Sender: TObject);

procedure WriteHexStr(ss:string);//запись строки в файл

//перевод из Ansi в hex

function StrToHexStr(str:string):string;

function StrDelSpaseHex(s:string):string;

private

{ Private declarations }

public

{ Public declarations }

end;

//Глобальные переменные

var

Form1: TForm1;

ThisProgram:Prog; //параметр программы (контроль за наличием сегментов)

Reg16,Reg8:arrayofstring; //динамический список имен регистров (нумерация для мнемокодов)

ComReadPos:integer; //cчетчик команд

ComBytePos:integer; //cчетчик байтов

DataBytes:integer; //для формирования сегмента данных

ErrorControl:string; //для хранения ошибки

VariableAdr:string; //для формирования таблицы ссылок

RegLen:string; //хранение размера регистра при анализировании команды

VarLen:string; //хранение размера переменной при анализировании команды

VarCode:string; //хранение адреса переменной при анализировании команды

FileSave:file of byte;//файл с кодом

FileLoad:textfile;//Выходной файл

implementation

{$R *.dfm}

//добавить к мнемокоду номер рeгистра*k, указанного в аргументе: ('A0' + 'cx' = 'A1')

function TForm1.insRegMul(mem:string; arg:string; koef:integer):string;

var pos:integer; intcode:integer;

begin

IsReg(arg);

pos:=0;

intcode:=ord(NexStrToStr(mem)[1]); //16-ый код - строка (пример: 'A0') переводится в целое число

//получение номера регистра:

if (RegLen='R16') then for pos:=0 to length(Reg16) do if arg=Reg16[pos] then break;

if (RegLen='R8') then for pos:=0 to length(Reg8) do if arg=Reg8[pos] then break;

intcode:=intcode+pos*koef; //добавление позиции регистра к мнемокоду

mem:=IntToHex(intcode,2); //перевод обратно в 16-ый код - строку

insRegMul:=mem;

end;

//добавить к мнемокоду номер рeгистра, указанного в аргументе: ('A0' + 'cx' = 'A1')

function TForm1.insReg(mem:string; arg:string):string;

var pos:integer; intcode:integer;

begin

isReg(arg);

pos:=0;

intcode:=ord(NexStrToStr(mem)[1]); //16-ый код - строка (пример: 'A0') переводится в целое число

//получение номера регистра:

if (RegLen='R16') then for pos:=0 to length(Reg16) do if arg=Reg16[pos] then break;

if (RegLen='R8') then for pos:=0 to length(Reg8) do if arg=Reg8[pos] then break;

edit1.Text:=edit1.Text+'$pos='+inttostr(pos);

intcode:=intcode+pos; //добавление позиции регистра к мнемокоду

mem:=IntToHex(intcode,2); //перевод обратно в 16-ый код - строку

insReg:=mem;

end;

function TForm1.StrToHexStr(str:string):string; //перевод текста в строку в код 16 с/c

var pos:integer; hexstr:string;

begin

hexstr:='';

for pos:=1 to length(str) do hexstr:=hexstr+IntToHex(ord(str[pos]),2);

StrToHexStr:=hexstr;

end;

procedure TForm1.SlideDown;

begin

Code.Perform(WM_VSCROLL, SB_LINEDOWN, 1);

MashCode.Perform(WM_VSCROLL, SB_LINEDOWN, 1);

ComBytePosMemo.Perform(WM_VSCROLL, SB_LINEDOWN, 1);

end;

procedure TForm1.SlideUp;

begin

Code.Perform(WM_VSCROLL, SB_LINEUP, 1);

MashCode.Perform(WM_VSCROLL, SB_LINEUP, 1);

ComBytePosMemo.Perform(WM_VSCROLL, SB_LINEUP, 1);

end;

procedure TForm1.TranslAndSaveMenuClick(Sender: TObject);

begin

ExeAll.Click; //транслирование всей программы

CreateObjFile.Click; //Формирование объектного файла

SaveMenu.Click; //сохранение

end;

functionTForm1.GetVarCodeByName(name:string):string; //из таблицы переменных взять код переменной по имени

var row:integer; adrs:string;

begin

adrs:='';

for row:=1 to Varibles.RowCount-1 do if Varibles.Cells[0,row]=name then begin GetVarCodeByName:=Varibles.Cells[1,row];VarLen:=Varibles.Cells[3,row];exit;end;

ErrorControl:='<Необъяв. перемен.>';

end;

procedure TForm1.DataTableWrite(Varible:string; Len:string;Code:string); //запись в таблицу переменных

varrow:integer;

begin

//ComBytePos глобальная переменная - счетчик байтов для записи переменных в сегмент данных

Varibles.RowCount:=Varibles.RowCount+1;

row:=Varibles.RowCount-1;

Varibles.Cells[0,row]:=Varible;

Varibles.Cells[1,row]:=IntToHex(DataBytes,4);

Varibles.Cells[2,row]:=Code;

if Len='db' then Begin

DataBytes:=DataBytes+1;

Varibles.Cells[3,row]:='V8';

end;

if Len='dw' then Begin

DataBytes:=DataBytes+2;

Varibles.Cells[3,row]:='V16';

end;

end;

function TForm1.DecompositeDirective(DrcStr:string):directive;

varpos:integer;

begin

//начальные значения

DecompositeDirective.part1:='';

DecompositeDirective.part2:='';

DecompositeDirective.part3:='';

//установка ограничения для строки-директивы

DrcStr:=DrcStr+' ';

//1)извлечение первой части:

for pos:=1 to length(DrcStr) do if DrcStr[pos]=' ' then begin

DecompositeDirective.part1:=copy(DrcStr,1,pos-1);

Delete(DrcStr,1,pos);

Break;

end;

//2)извлечение второй части:

for pos:=1 to length(DrcStr) do if DrcStr[pos]=' ' then begin

DecompositeDirective.part2:=copy(DrcStr,1,pos-1);

Delete(DrcStr,1,pos);

Break;

end;

//3)извлечение третьей части:

for pos:=1 to length(DrcStr) do if DrcStr[pos]=' ' then begin

DecompositeDirective.part3:=copy(DrcStr,1,pos-1);

Delete(DrcStr,1,pos);

Break;

end;

end;

function TForm1.AnalysisDirective(DrcStr:string):directive;

var drc:directive;

begin

drc:=DecompositeDirective(DrcStr);

with drc do BEGIN

exist:=false;

//dd,dw

if (part1<>'') and ((part2='dw')or(part2='db')) and isImm(part3) then begin

MashCode:=ImmToHex(part3,part2);

DataTableWrite(part1,part2,MashCode);

exist:=true;

end;

//dd,dw без имени переменной

if ((part1='dd')or(part1='dw')) and isImm(part2) then begin

MashCode:=ImmToHex(part2,part1);

DataTableWrite('',part1,MashCode);

exist:=true;

end;

if (part1='masm') then exist:=true;

if (part1='.code') then exist:=true;

if (part1='.data') then exist:=true;

if (part1='.model') and (part2='small')then exist:=true;

if (part1='.stack') then exist:=true;

if (part1='.286') then exist:=true;

if (part1='end') then exist:=true;

if (part1='data') and (part2='segment') then exist:=true;

if (part1='data') and (part2='ends') then exist:=true;

if (part1='code') and (part2='segment') then exist:=true;

if (part1='code') and (part2='ends') then exist:=true;

if (part1='assume') then exist:=true;

if (part1='ends') then exist:=true;

if (part1='end') and (part2='main') then exist:=true;

END;

AnalysisDirective:=drc;

end;

procedure TForm1.ComExe; //транслирование строки программы

varcom:command; //команда записанная в специальной записи - команда

drc:directive; //директива записанная в специальной записи - директива

comstr:string; //команда в текстовом виде

pos:integer;

begin

//добавление строк в байтовый счетчик, кодовую часть и часть данных

MashCode.Lines.Add('');

ComBytePosMemo.Lines.Add('');

//проверка на строку-пустоту или строку - сплошной комментарий:

//..если встречается такая строка, то выход без обработки

comstr:=ComRead;

//если строка в коде программы является полностью комментарием:

if length(comstr)>=1 then begin

pos:=1; while (comstr[pos]=' ')and(pos<length(comstr)) do inc(pos);

if comstr[pos]=';' then exit;

end;

//если строка является пустой:

if comstr='' then exit;

ComBytePosMemo.Lines[ComReadPos]:=IntToHex(ComBytePos,4);

//обработка команд - операторов

com:=AnalysisCommand(comstr);

MashCode.Lines[ComReadPos]:=com.MashCode;

if com.ByteLen<>'' then ComBytePos:=ComBytePos + strtoint(com.ByteLen);

//обработка команд - директив

drc:=AnalysisDirective(ComRead);

//MashData.Lines[ComReadPos]:=drc.MashCode;

//----------------------------------------------------------------------------->

//выявление ошибок в синтаксисе:

ifcom.MashCode<>'' thencom.exist:=true; //если есть машинный код то оператор распознан

if (notcom.exist) and (notdrc.exist) //если ни директива, ни оператор не распознаны то:

then MashCode.Lines[ComReadPos]:='<Неизв. ком.>';

//анализ сообщений об ошибках:

if ErrorControl<>'' then MashCode.Lines[ComReadPos]:=ErrorControl;

ErrorControl:=''; //стирание сообщений об ошибках

//----------------------------------------------------------------------------->

end;

procedure TForm1.MarksLinksTableWrite(Mname,LBytepos:string);

varrow:integer;

begin

//поиск введенной метки среди существующих

row:=1; while (row<=markslinks.RowCount-1) do begin

if markslinks.Cells[0,row]=Mname then begin

//если поиск успешен - то вывод ошибки (повторное описание ссылки метки)

ErrorControl:='<Переопр. метки>';

exit;

end;

inc(row);

end;

//если вносимой ссылки нет - то внести её

markslinks.RowCount:=row+1; //row указывает на конец таблицы

if Mname <>'' then markslinks.Cells[0,row]:=Mname;

if LBytepos<>'' then markslinks.Cells[1,row]:=LBytepos;

markslinks.FixedRows:=1; //выделить заголовок таблицы

end;

procedure TForm1.MarkTableWrite(Mname,LBytepos,CBytepos,Strpos:string);

var row:integer;

begin

//добавление ссылки метки:

ifLBytepos<>'' thenbegin

//добавление ко всем меткам ссылок

row:=1; while (row<=marks.RowCount-1) do begin

if marks.Cells[0,row]=Mname then if LBytepos<>'' then

marks.Cells[1,row]:=LBytepos;

inc(row);

end;

end;

//добавление оператора, использующего метку

if CBytepos<>'' then begin

marks.RowCount:=marks.RowCount+1;

marks.FixedRows:=1;

row:=marks.RowCount-1;

if Mname <>'' then marks.Cells[0,row]:=Mname;

if CBytepos<>'' then marks.Cells[2,row]:=CBytepos;

if Strpos <>'' then marks.Cells[3,row]:=Strpos;

exit;

end;

end;

function TForm1.ModifyMarkAdress:string; //расчет смещений и добавление их в сегмент кода

var row,l:integer;

begin

for row:=1 to marks.RowCount-1 do begin

if MashCode.Lines[strtoint(marks.Cells[3,row])]='E8' then l:=4

else l:=2;

if (marks.Cells[0,row]<>'')and(marks.Cells[2,row]<>'') then begin

if (strtoint(marks.Cells[1,row])<strtoint(marks.Cells[2,row])) then begin

MashCode.Lines[strtoint(marks.Cells[3,row])]:=

MashCode.Lines[strtoint(marks.Cells[3,row])]+

InvertBytes(IntToHex(256-(strtoint(marks.Cells[2,row])-strtoint (marks.Cells[1,row])),l)); end

else

MashCode.Lines[strtoint(marks.Cells[3,row])]:=

MashCode.Lines[strtoint(marks.Cells[3,row])]+

InvertBytes(IntToHex(strtoint(marks.Cells[1,row])-strtoint(marks.Cells[2,row]),l));

end;

end;

procedure TForm1.AddLinksInMarkers; //добавление ссылок в таблицу меток

var row:integer;

begin

row:=1; while row<=markslinks.RowCount do begin

MarkTableWrite(markslinks.Cells[0,row],markslinks.Cells[1,row],'','');

inc(row);

end;

end;

function TForm1.IntToHexStr(int:integer):string; //преобразование целого числа в строку - 16-ую запись этого числа

var res:string;

begin

res:=IntToHex(int,2);

while length(res)>2 do delete(res,1,1);

IntToHexStr:=res;

end;

function TForm1.DecompositeCommand(comstr:string):Command;

var posi:integer; oper,mark,arg1,arg2:string;

begin

//обнуление параметров:

mark:='';

oper:='';

arg1:='';

arg2:='';

//для форматов "mark:movax,bx; comments" =метка + команда с двумя операндами + комментарий

// "movax,bx" =команда с двумя операндами

// "incax" =команда с одним операндом

// "aam" =команда без операндов

//если строка является полностью комментарием

if length(comstr)>=1 then begin

posi:=1; while (comstr[posi]=' ')and(posi<length(comstr)) do inc(posi);

if comstr[posi]=';' then comstr:='';

end;

//установка ограничения для строки-команды

comstr:=comstr+' ';

//замена разделителя комментария (символ ';') на пробел

posi:=pos(';',comstr); if posi>0 then comstr[posi]:=' ';

//1)извлечение метки

for posi:=1 to length(comstr) do if comstr[posi]=':' then begin

mark:=copy(comstr,1,posi-1);

Delete(comstr,1,posi);

Break;

end;

//2)извлечение мнемокода операции

for posi:=1 to length(comstr) do if comstr[posi]=' ' then begin

oper:=copy(comstr,1,posi-1);

Delete(comstr,1,posi);

Break;

end;

//3)извлечение первого операнда

for posi:=1 to length(comstr) do if comstr[posi]=',' then begin

arg1:=copy(comstr,1,posi-1);

Delete(comstr,1,posi);

Break;

end;

//4)извлечение второго операнда

for posi:=1 to length(comstr) do if (comstr[posi]=' ') then begin

arg2:=copy(comstr,1,posi-1);

Delete(comstr,1,posi);

Break;

end;

//Для данного алгоритма: если второй операнд есть, а первого нет то это значит что команда одноаргументная:

//..нужно выполнить пересылку аргумента из 2 в 1:

if (arg1='')and(arg2<>'') then begin

arg1:=arg2;

arg2:='';

end;

//Запись результатов в параметр возвращаемый процедурой:

DecompositeCommand.mark:=mark;

DecompositeCommand.oper:=oper;

DecompositeCommand.arg1:=arg1;

DecompositeCommand.arg2:=arg2;

end;

//Удаление пробелов перед и после команды, а также двойных пробелов и пробелов

//..перед символами разделения (запятая и т. д.)

function TForm1.DeleteSpace(str:string):string;

var ps:integer;

begin

if str=' ' then str:='';

if str='' then exit;

ps:=1;

while ps <= length(str) do begin

if (str[ps]=#9) then begin delete(str,ps,1); continue end;

inc(ps);

end;

//удаление пробелов до и после команды:

while ((str[1]=' ')and(length(str)>1)) do delete(str,1,1);

while ((str[length(str)]=' ')and(length(str)>1)) do delete(str,length(str),1);

//удаление повторных пробелов:

ps:=1; while ps <= length(str)-1 do begin

if (str[ps]=' ') then while (str[ps+1]=' ') do begin delete(str,ps,1); end;

inc(ps);

end;

//удаление пробелов рядом с разделителем - запятой

ps:=Pos(',',str);

if ps>0 then begin

if str[ps+1]=' ' then delete(str,ps+1,1);

if str[ps-1]=' ' then delete(str,ps-1,1);

end;

DeleteSpace:=str;

end;

function TForm1.ComIs:string; //Есть ли команда или уже конец файла

begin

if (ComReadPos<Code.Lines.Count) then ComIs:=''

else ComIs:='EOF';

end;

function TForm1.ComNext:string; //Переход на следующую команду или сброс:

begin

inc(ComReadPos);

end;

//Считывание очередной считанной команды и возврат её функцией в текстовом виде

function TForm1.ComRead:string;

begin

//LowerCase - все буквы (от A до Z) устанавл. прописными

ComRead:=LowerCase(DeleteSpace(Code.Lines[ComReadPos])); //DeleteSpace - удаление пробелов

end;

//Получение Imm16 с перестановкой байтов в Imm16 и убирание символа 'h'/'a'

function TForm1.ImmToHex(imm:string;len:string):string;

const HexChar:set of char=['0'..'9','A'..'F','a'..'f'];

var i,l,temp:integer;

c:char;

begin

if imm='' then exit;

l:=-1;

c:= imm[Length(imm)];

Delete(imm,Length(imm),1);

if len ='dw' then l:=4;

if len ='db' then l:=2;

i:=1;

while i<=Length(imm) do

if imm[i] in HexChar then inc(i)

else Delete(imm,i,1);

if imm='' then exit;

While (imm[1]='0') and (length(imm)>1) do Delete(imm,1,1);

temp:=0;

if c='b' then begin for i:=Length(imm) to 1 do

if imm[i]='1' then temp:=temp+ round(intpower(2,length(imm)-i));

imm:=IntToHex(temp,l);end;

If length(imm)>l then begin ErrorControl:='<Несоответствие типов>';exit; end;

while length(imm)<l do imm:='0'+imm;

ImmToHex:=Uppercase(imm);

end;

//Получение кода в 16 c/c, являющегося смещением относительно положения si (для операндов вида [si+N])

function TForm1.cnvData(dat:string):string;

begin

ifpos('+',dat)>0 then //если указано смещение т.е. si+N, где N - велич. смещения

cnvData:=copy(dat,pos('+',dat)+1,2) //получение 2-х символов после символа +, подразумевается что эти символы число в 16 с/c

elsecnvData:='*'; //смещение не указано

end;

// Проверка на непосредственный операнд (пример movax,0140h - 0140h = Imm16):

function TForm1.isImm(arg:string):boolean;

const hexset: set of char=['0'..'9','a'..'f'];

typeset: set of char=['b','h'];

var pos:integer;

begin

If Length(arg)<=1 then begin isImm:=false;exit;end;

isImm:=true;

if not (arg[length(arg)] in typeset) then begin isImm:=false;exit;end;

for pos:=1 to length(arg)-1 do if not (arg[pos] in hexset) then begin isImm:=false;exit;end;

//не является ли непосредственный операнд регистром:

for pos:=0 to length(Reg16)-1 do if (Reg16[pos]<>'') then if (arg=Reg16[pos]) then begin isImm:=false; break; end;

for pos:=0 to length(Reg8)-1 do if (Reg8[pos]<>'') then if (arg=Reg8[pos]) then begin isImm:=false; break; end;

end;

// Проверка на непосредственный операнд (пример movax,0140h - 0140h = Imm16):

function TForm1.isReg(arg:string):boolean;

var pos:integer;

begin

isReg:=false; //убрать признак, что аргумент регистр

RegLen:=''; //убрать информацию о длине регистра

//является ли операнд - регистром:

for pos:=0 to length(Reg16)-1 do if (Reg16[pos]<>'') then

if (arg=Reg16[pos]) then begin isReg:=true; RegLen:='R16'; exit; end;

for pos:=0 to length(Reg8)-1 do if (Reg8[pos]<>'') then

if (arg=Reg8[pos]) then begin isReg:=true; RegLen:='R8'; exit; end;

end;

// Проверка на взаимодействие с областью сегмента данных через si (movax,[si+4]):

function TForm1.isData(str:string):boolean;

begin

isData:=false;

if Pos('[',str)>0 then if Pos(']',str)>0 then if Pos('si',str)>0 then isData:=true;

end;

// Функция преобразования строки с шестнадцатеричными символами эквивалентной 1 байту в символ:

function TForm1.NexStrToStr(nexstr:string):string;

begin

if length(nexstr)=2 then NexStrToStr:=chr(strtoint('$'+nexstr));

if length(nexstr)=4 then NexStrToStr:=chr(strtoint('$'+copy(nexstr,1,2)))+

chr(strtoint('$'+copy(nexstr,3,2)));

if length(nexstr)=6 then NexStrToStr:=chr(strtoint('$'+copy(nexstr,1,2)))+

chr(strtoint('$'+copy(nexstr,3,2)))+

chr(strtoint('$'+copy(nexstr,5,2)));

end;

procedure TForm1.NewProgramButtonClick(Sender: TObject);

begin

//установка указателя для считывания на начало программы

ComReadPos:=0;

//установка счетчика положения команд в байтах на начало

ComBytePos:=0;

//обнуление счетчика для записи переменных в сегмент даных

DataBytes:=0;

//обнуление

marks.RowCount:=1; //таблицы поправок

varibles.RowCount:=1; //таблицы переменных

markslinks.RowCount:=1; //таблицы меток

//обнуление буферов - содержимых сегментов

VariableAdr:='';

ComBytePosMemo.Text:='';

MashCode.Text:='';

Title.Text:='';

CodeSeg.Text:='';

DataSeg.Text:='';

end;

function TForm1.IsVar(arg:string):boolean; //Является ли аргумент переменной

var i:integer;

begin

IsVar:=False;

for i:=1 to Form1.Varibles.RowCount do

if Varibles.Cells[0,i]=arg then begin

IsVar:=True;

VarCode:=Varibles.Cells[2,i];

VarLen:=Varibles.Cells[3,i];

Exit;

end;

end;

function TForm1.GerArgType(Arg:string):string;

begin

GerArgType:='';

if isReg(arg) then GerArgType:=RegLen;

if isVar(arg) then GerArgType:=VarLen;

if IsImm(arg) then GerArgType:='Imm';

if IsData(arg) then GerArgType:='Data'

end;

//Возврат машинного кода после распознавания мнемокода, установка длины команды, проверка существования команды

function TForm1.AnalysisCommand (comstr:string):command;

var com:command;

Arg1Type,Arg2Type:string;

begin

com:=DecompositeCommand(comstr);

//обнуление выходных параметров - если программа не опознана то выводится

//..предупреждение о неизв. команде

com.MashCode:='';

com.ByteLen:='';

com.exist:=false; //первоначально команда считается не распознанной

with com do BEGIN

Arg1Type:=GerArgType(arg1);

Arg2Type:=GerArgType(arg2);

oper:=Lowercase(oper);

arg1:=Lowercase(arg1);

arg2:=Lowercase(arg2);

if (oper='mov') then begin//------------------------------------------------MOV

//предпроверка

//проверка правильности использования команды:

if (Arg1Type='R8') and (Arg2Type='R16') then begin ErrorControl:='<Неcоотв. типов арг.>'; exit; end;

if (Arg1Type='R16') and (Arg2Type='R8') then begin ErrorControl:='<Неcоотв. типов арг.>'; exit; end;

if (Arg1Type='V8') and (Arg2Type='R16') then begin ErrorControl:='<Неcоотв. типов арг.>'; exit; end;

if (Arg1Type='R16') and (Arg2Type='V8') then begin ErrorControl:='<Неcоотв. типов арг.>'; exit; end;

if (Arg1Type='V16') and (Arg2Type='R8') then begin ErrorControl:='<Неcоотв. типов арг.>'; exit; end;

if (Arg1Type='R8') and (Arg2Type='V16') then begin ErrorControl:='<Неcоотв. типов арг.>'; exit; end;

//проверка указания всех аргументов

if (arg1='')or(arg2='') then begin ErrorControl:='<Неуказ. все аргум.>'; exit; end;

if (arg1='ds') then if (arg2='ax') then begin //mov ax-ds

MashCode:='8ED8';

ByteLen:='2'; end;

//reg to reg

if (Arg1Type='R16')and(Arg2Type='R16') then begin MashCode:='8B'+InsReg(InsRegMul('c0',arg1,8), arg2); ByteLen:='2'; end;//mov R16-R16

if (Arg1Type= 'R8')and(Arg2Type= 'R8') then begin MashCode:='8A'+InsReg(InsRegMul('c0',arg1,8), arg2); ByteLen:='2'; end; //mov R8-R8

//imm to reg

if (Arg1Type= 'R16')and(Arg2Type= 'Imm') then begin MashCode:=InsReg('B8',arg1)+InvertBytes(ImmToHex(arg2,'dw')); ByteLen:='3'; end; //mov R16-Imm16

if (Arg1Type= 'R8')and(Arg2Type= 'Imm') then begin MashCode:=InsReg('8A',arg1) +ImmToHex(arg2,'db'); ByteLen:='2'; end; //mov R8-Imm8

//var to reg

if (Arg1 = 'al')and(Arg2Type= 'V8') then begin MashCode:='A0'+InvertBytes(GetVarCodeByName(arg2));ByteLen:='3';VariableAdr:=VariableAdr+'C4'+IntToHex(combytepos+1,2)+'5401 ';end//mov al-var8

else if (Arg1Type= 'R8')and(Arg2Type= 'V8') then begin MashCode:='8A'+InsRegMul('06',arg1,8)+InvertBytes(GetVarCodeByName(arg2));VariableAdr:=VariableAdr+'C4'+IntToHex(combytepos+2,2)+'5401 ';ByteLen:='4';end;//mov R8-var8

if (Arg1 = 'ax')and(Arg2Type='V16') then begin MashCode:='A1'+InvertBytes(GetVarCodeByName(arg2));ByteLen:='3';VariableAdr:=VariableAdr+'C4'+IntToHex(combytepos+1,2)+'5401 ';end//mov ax-var16

else if (Arg1Type='R16')and(Arg2Type='V16') then begin MashCode:='8B'+InsRegMul('06',arg1,8)+InvertBytes(GetVarCodeByName(arg2));VariableAdr:=VariableAdr+'C4'+IntToHex(combytepos+2,2)+'5401 ';ByteLen:='4';end;//mov R16-var16

//reg to var

if (Arg2 = 'al')and(Arg1Type= 'V8') then begin MashCode:='A2'+InvertBytes(GetVarCodeByName(arg1));ByteLen:='3';VariableAdr:=VariableAdr+'C4'+IntToHex(combytepos+1,2)+'5401 ';end//mov var8-al

else if (Arg2Type= 'R8')and(Arg1Type= 'V8') then begin MashCode:='88'+InsRegMul('06',arg2,8)+InvertBytes(GetVarCodeByName(arg1));VariableAdr:=VariableAdr+'C4'+IntToHex(combytepos+2,2)+'5401 ';ByteLen:='4';end;//mov var8-R8

if (Arg2 = 'ax')and(Arg1Type='V16') then begin MashCode:='A3'+InvertBytes(GetVarCodeByName(arg1));ByteLen:='3';VariableAdr:=VariableAdr+'C4'+IntToHex(combytepos+1,2)+'5401 ';end//mov ax-var16

else if (Arg2Type='R16')and(Arg1Type='V16') then begin MashCode:='89'+InsRegMul('06',arg2,8)+InvertBytes(GetVarCodeByName(arg1));VariableAdr:=VariableAdr+'C4'+IntToHex(combytepos+2,2)+'5401 ';ByteLen:='4';end;//mov var16-R16

if (arg1='ax') then if (arg2='@data') or (arg2='data') then begin //mov ax-segname @Data

MashCode:='B8'+'0000';

ByteLen:='3';

//вспомогательный сегмент 9С05 для установки сегмента данных будет выведен:

ThisProgram.isDataSeg:=True; end;

if isReg(arg1) then if isData(arg2) then begin //mov Reg - data [si+n]

if cnvData(arg2)<>'*' then begin MashCode:='8B'+InsRegMul('44',arg1,8)+cnvData(arg2); ByteLen:='3'; end

else begin MashCode:='8B'+InsRegMul('04',arg1,8); ByteLen:='2' end;

end;

//послепроверка

if mashcode='' then ErrorControl:='<Неизв. аргумент>';

end;//---------------------------------------------------------------------/MOV

//Базовые команды:------------------------------------------------------------->

//int

if (oper='int') then if arg1type='Imm' then begin

MashCode:='CD'+ImmToHex(arg1,'db');

ByteLen:='2';

end;

//nop

if (oper='nop') then begin MashCode:='90'; ByteLen:='1'; end;

// dec mark

if (oper='dec') then begin

MashCode:='FF'+'0E'+InvertBytes(GetVarCodeByName(arg1));

ByteLen:='5';

end;

//jmp mark

if (oper='jg') then begin

MarkTableWrite(arg1,'',inttostr(ComBytePos+2),inttostr(ComReadPos));

MashCode:='7F';

ByteLen:='2';

end;

//add R16 - imm16

if (oper='add') then begin

if (arg1='ax') and (arg2Type='Imm') then begin MashCode:='05'+InvertBytes(ImmToHex(arg2,'dw')); ByteLen:='3'; end

end;

//ror R16 - imm8

if (oper='ror') then begin

if (Arg1Type='R16') and (Arg2Type='Imm') then begin

MashCode:='C1'+InsReg('C8',arg1)+ImmToHex(arg2,'db'); ByteLen:='3'; end;

end;

//mark: (место, куда осуществляется переход по метке)

if (mark<>'') then begin

MarksLinksTableWrite(mark,inttostr(ComBytePos));

exist:=true;

end;

END;

If Com.MashCode<>'' then Com.exist:=true;

AnalysisCommand:=com;

end;

procedure TForm1.Exit1Click(Sender: TObject);

begin

Application.Terminate; //выход из программы

end;

procedure TForm1.FormCreate(Sender: TObject);

var pos:integer;

begin

//параметры программы

//изначально ни один из сегментов не присутствует

ThisProgram.isCodeSeg:=False;

ThisProgram.isDataSeg:=False;

//имена регистров 16разр:

SetLength(Reg16,20); //число возможных регистров

for pos := 0 to Length(Reg16)-1 do Reg16[pos]:='';

Reg16[0]:='ax';

Reg16[1]:='cx';

Reg16[2]:='dx';

Reg16[3]:='bx';

Reg16[6]:='si';

Reg16[7]:='di';

//имена регистров 8разр:

SetLength(Reg8,8); //число возможных регистров

for pos := 0 to Length(Reg8)-1 do Reg8[pos]:='';

Reg8[0]:='al';

Reg8[1]:='cl';

Reg8[2]:='dl';

Reg8[3]:='bl';

Reg8[4]:='ah';

Reg8[5]:='ch';

Reg8[6]:='dh';

Reg8[7]:='bh';

//установка указателя для считывания на начало программы

ComReadPos:=0;

//установка счетчика положения команд в байтах на начало

ComBytePos:=0;

//обнуление счетчика для записи переменных в сегмент даных

DataBytes:=0;

//таблица меток

marks.RowCount:=1;

marks.Cells[0,0]:='Имя метки';

marks.Cells[1,0]:='Метка';

marks.Cells[2,0]:='Вызов метки';

marks.Cells[3,0]:='Строка';

//таблица переменных

varibles.RowCount:=1;

varibles.Cells[0,0]:='Имя';

varibles.Cells[1,0]:='Адрес';

varibles.Cells[2,0]:='Код';

varibles.Cells[3,0]:='Длина';

//таблица ссылок меток

markslinks.RowCount:=1;

markslinks.Cells[0,0]:='Имя';

markslinks.Cells[1,0]:='Метка';

ErrorControl:=''; //стирание сообщений об ошибках

end;

function TForm1.CharToByte(C:char):byte;

var cc:byte;

begin

cc:=0;

case c of

'0'..'9': cc:=strtoint(c);

'A':cc:=$A;

'B':cc:=$B;

'C':cc:=$C;

'D':cc:=$D;

'E':cc:=$E;

'F':cc:=$F;

end;

CharToByte:=cc;

end;

function TForm1.HexByteToByte(s:string):byte;

begin

HexByteToByte:=((CharToByte(s[1]) shl 4)and(240))or((CharToByte(s[2])) and(15))

end;

procedure TForm1.WriteHexStr(ss:string);

var

bb:byte;

i:integer;

begin

i:=1;

while i<=Length(ss) do begin

bb:=HexByteToByte(copy(ss,i,2));

Write(FileSave,bb);

i:=i+2;

end;

end;

function TForm1.StrDelSpaseHex(s:string):string;

const HexSet:set of Char=['0'..'9','A'..'F'];

var ss:string;

i:integer;

begin

i:=1;

ss:=s;

while i<=length(ss) do

if not (Uppercase(ss[i])[1] in HexSet) then Delete(ss,i,1)

else inc(i);

StrDelSpaseHex:=ss;

end;

function Tform1.AddControlByte(s:string):string;

var sum,i:integer;

begin

i:=1;sum:=0;

s:=StrDelSpaseHex(s);

while i<=length(s) do begin

Sum:=Sum+HexByteToByte(copy(s,i,2));

i:=i+2;

end;

sum:=($100-sum mod $100)mod $100;

AddControlByte:=Form1.IntToHexStr(sum);

end;

function TForm1.InvertBytes(s:string):string;//Сместить порядок байтов

var i:integer;

ss:string;

begin

ss:='';

for i:=Length(s)div 2 downto 1 do

ss:=ss+copy(s,2*i-1,2);

InvertBytes:=ss;

end;

procedure TForm1.CreateObjFileClick(Sender: TObject);

var s,s1,s2:string;

i:integer;

Strings:array[1..6]of string;

begin

//смещения прибавляемые к записям в объектном файле (+2 +4 +8)- зависят от длины след за них добавочных записей

//формирование заголовка

//1 строчка

s:=OpenDialog1.FileName;

for I:=length(S) downto 1 do if S[i]='\' then begin Delete(s,1,i);break;end;

s1:=InvertBytes(IntToHex(length(S)+2,4));

s2:=IntToHex(length(S),2);

Strings[1]:='80 '+s1+s2+StrToHexStr(S);

Strings[1]:=Strings[1]+AddControlByte(Strings[1]);

Strings[2]:='88 '+IntToHexStr(length('Turbo Assembler Version 4.1')+4)+'0000 001C'+StrToHexStr('Turbo Assembler Version 4.1');

Strings[2]:=Strings[2]+AddControlByte(Strings[2]);

Strings[3]:='88 '+IntToHexStr(length(S)+8)+'0040 E97A 74A5 4209 '+StrToHexStr(S);

Strings[3]:=Strings[3]+AddControlByte(Strings[3]);

Strings[4]:='98 07 00 60 '+IntToHexStr(DataBytes)+' 00 02 01 01 ';

Strings[4]:=Strings[4]+AddControlByte(Strings[4]);

Strings[5]:='98 07 00 60 '+IntToHexStr(ComBytePos)+' 00 03 01 01 ';

Strings[5]:=Strings[5]+AddControlByte(Strings[5]);

Title.Text:=Strings[1]+#13#10+

Strings[2]+#13#10+

Strings[3]+#13#10+

'88 03 00 40 E9 4C'+#13#10+

'96 02 00 00 68'+#13#10+

'88 03 00 40 A1 94'+#13#10+

'96 06 00 04 44 41 54 41 46'+#13#10+

Strings[4]+#13#10+

'96 06 00 04 43 4F 44 45 45'+#13#10+

Strings[5]+#13#10+

'88 04 00 40 A2 01 91';

//формирование кодового сегмента

CodeSeg.Text:='A0 '+InvertBytes(IntToHex(ComBytePos+4,4))+'02 0000'+StrDelSpaseHex(MashCode.Text);

CodeSeg.Text:=CodeSeg.Text+AddControlByte(CodeSeg.Text);

//формировани сегмента данных

Strings[6]:='';

for i:=1 to Varibles.RowCount-1 do

Strings[6]:=Strings[6]+InvertBytes(Varibles.Cells[2,i]);

DataSeg.Text:='A0 '+InvertBytes(IntToHex(DataBytes+4,4))+' 01 00 00 '+Strings[6];

DataSeg.Text:=DataSeg.Text+AddControlByte(DataSeg.Text);

EndFile.Text:='8A 0700 C100 0202 0000 AA';

DataSourceSeg.Text:='9C '+InvertBytes(IntToHex(Length(StrDelSpaseHex(VariableAdr))div 2+1,4))+' '+VariableAdr;

DataSourceSeg.Text:=DataSourceSeg.Text+AddControlByte(DataSourceSeg.Text);

end;

procedure TForm1.ClearCodeButtonClick(Sender: TObject); //очистка поля для ввода кода прогр.

begin

Code.Clear;

DataSourceSeg.Clear;

EndFile.Clear;

end;

procedure TForm1.exeAllClick(Sender: TObject);

begin

NewProgramButtonClick(NewProgramButton);

while ComIs<>'EOF' do begin

ComExe;

ComNext;

end;

AddLinksInMarkers; //пересылка всех меток из таблицы меток в таблицу поправок

ModifyMarkAdress; //расчет смещений и добавление их к командам перехода

end;

procedure TForm1.CodeDblClick(Sender: TObject);

var

i:integer;

Str:String;

begin

i:=0;

If OpenDialog1.Execute then begin

AssignFile(FileLoad, OpenDialog1.FileName);

Reset(FileLoad);

Code.Clear;

Memo1.Clear;

while not eof(FileLoad) do

begin

inc(i);

ReadLn(FileLoad,Str);

Code.Lines.Add(Str);

Memo1.Lines.Add(IntToStr(I));

end;

CloseFile(FileLoad);

end;

ScrollBar1.Max:=Code.Lines.Count;

ScrollBar1.Position:= Code.Lines.Count;

ScrollBar1.Tag:=Code.Lines.Count;

end;

procedure TForm1.ScrollBar1Change(Sender: TObject);

var k:integer;

begin

k:=ScrollBar1.Position-ScrollBar1.Tag;

If K>0 then begin

Code.Perform (EM_SCROLL, SB_LINEDOWN, K);

ComBytePosMemo.Perform(EM_SCROLL, SB_LINEDOWN, K);

MashCode.Perform (EM_SCROLL, SB_LINEDOWN, K);

Memo1.Perform (EM_SCROLL, SB_LINEDOWN, K);

end

else begin

Code.Perform (EM_SCROLL, SB_LINEUp, K);

ComBytePosMemo.Perform(EM_SCROLL, SB_LINEUp, K);

MashCode.Perform (EM_SCROLL, SB_LINEUp, K);

Memo1.Perform (EM_SCROLL, SB_LINEUp, K);

end;

Scrollbar1.Tag:=Scrollbar1.Position;

end;

Алгоритм работы программной реализации разрабатываемого компилятора

Компилятор, разработанный в данной курсовой работе, является однопроходным. Он использует две таблицы:

1) Таблица переменных, состоящая из полей: имя, адрес, код и длина.

2) Таблица меток(поправок), состоящая из полей: имя метки, положение метки, вызов метки, строка в которой вызывают метку.

Обработка происходит следующим образом.

Строка файла разбивается на 3 поля. Происходит обработка команд-директив или команд-операторов, также присутствуют проверки на строку-пустоту или строку - сплошной комментарий. Если директива то с помощью функции Data Table Write заносим в таблицу переменных название, адрес, машинный код и вычисляем длину. Если команда-оператор то определяем команду с помощью функции Analysis Command. Если команда с меткой, то переводим ее частично в машинный код и в таблицу меток записываем имя метки, адрес вызова метки и строку откуда вызывали. Если нашли метку записываем ее адрес в таблицу. После разбора всего файла вычисляем метки и добавляем к старым командам.

Заключение

Пример работы программы

Объектный код

Рис. 2 Получившийся объектный код при использовании компилятора TASM

Рис. 3 Получившийся объектный файл при работе программы

Расшифровка объектного кода откомпилированного примера.

80 0А 00 08 6B 6F 70 61 2E 61 73 6D 54 -запись названия исходного файла;

• 88 1A 00 00 00 1C 43 6F 6D 70 69 6C 65 72 20 4B 6F 70 79 6C 6F 76 61 20 4E 2E 53 2E 75 -- запись названия транслятора;

• 88 10 00 40 E9 34 67 C4 42 08 6B 6F 70 61 2E 61 73 6D 7C- вторая запись с название исходного файла;

• 88 03 00 40 E9 4C 96 02 00 00 68 88 03 00 40 A1 94- три постоянные записи;

• 96 06 00 04 44 41 54 41 46 -описания имени сегмента данных (DATА);

• 98 07 00 60 08 00 02 01 01 F5 - описание данных сегмента данных;

• 96 06 00 04 43 4F 44 45 45- описания имени сегмента кода (CODE);

• 98 07 00 60 15 00 03 01 01 E7- описание данных сегмента кода;

• 88 04 00 40 A2 01 91 - предсегментный блок;

• A0 0C 00 01 00 00 01 10 00 01 01 01 00 4CF3- содержимое сегмента данных;

• A0 19 00 02 00 00 A1 00 00 05 01 01 FF 0E 04 00 C1 C8 05 7F 01 90 A1 06 00 CD 21 59 - содержимое сегмента кода (A10000 - mov ax,a1, 050101FF - add ax,101h, 0E 04 00 - dec a3, C1 C8 05 - ror ax,5h, 7F 01 - jg @2, 90-nop, A1 06 00 - mov ax,c, CD 21 - int 21h);

• 9C 0D 00 C4 01 54 01 C4 08 54 01 C4 11 54 01 F2- таблица ссылок сегмента кода;

8A 0700 C100 0202 0000 AA - запись конца объектного файла.

Размещено на Allbest.ru


Подобные документы

  • Функции компилятора как системной обрабатывающей программы. Этапы компиляции: анализ и синтез. Разработка лексического анализатора. Алгоритм и программа лексического анализа. Реализация двухфазного компилятора. Описание логической структуры программы.

    курсовая работа [310,4 K], добавлен 26.03.2010

  • Структура, классификация и требования к реализации компилятора. Проектирование и реализация анализирующей части компилятора языка С++. Способы реализации лексического анализа. Алгоритм работы синтаксического анализатора. Принципы программной реализации.

    курсовая работа [774,2 K], добавлен 26.01.2013

  • Принцип работы транслятора. Исследование формата данных объектного файла шестнадцатиразрядной системы DOS для последующего преобразования его в файл программы. Используемые директивы и команды ассемблера. Алгоритмы программы и таблицы компилятора.

    контрольная работа [35,9 K], добавлен 07.07.2012

  • Краткая характеристика предметно-ориентированных языков, различия между "внутренними" и "внешними" DSL. Особенности работы транслятора (компилятора). Листинг программы для разработки простейшего калькулятора с использованием программной среды Java.

    лабораторная работа [57,8 K], добавлен 31.03.2017

  • Взаимосвязь стадий процесса проектирования сложных программных систем. Создание компилятора подмножества языка высокого уровня (Pascal) на язык Ассемблера. Структура входных и выходных данных, алгоритмы их обработки. Рабочая документация программы.

    курсовая работа [256,7 K], добавлен 27.07.2014

  • Разработка принципиальной схемы, выбор управляющего микроконтроллера. Общий алгоритм работы программы. Блок анализа и реализации команд, принятых от персонального компьютера. Описание используемых интерфейсов. Формат данных RS-232C, листинг программы.

    курсовая работа [1,2 M], добавлен 26.12.2012

  • Приемы программирования в Delphi. Алгоритм поиска альфа-бета отсечения, преимущества. Описание программного средства. Разработка программы, реализующая алгоритм игры "реверси". Руководство пользователя. Листинг программы. Навыки реализации алгоритмов.

    курсовая работа [357,1 K], добавлен 28.02.2011

  • Разработка гипотетической машины при помощи макросредств ассемблера. Разработка алгоритма для реализации обязательных команд: сравнения двух символьных строк; их обмена; определения длины слова. Основные функции обработки строки, листинг программы.

    курсовая работа [59,6 K], добавлен 14.07.2012

  • Построение компилятора с языка высокого уровня как одного из элементов системы программирования. Разработка компилятора ассемблера, модификация базы данных исходного макета. Загрузчик, эмулятор, отладчик. Использование Flex и Bison для программирования.

    курсовая работа [599,0 K], добавлен 04.11.2014

  • Разработка анализирующей части компилятора для выполнения проверки исходной программы на соответствие грамматике языка, правилам семантики и построения внутреннего представления. Описание анализаторов: лексического, синтаксического и семантического.

    контрольная работа [704,9 K], добавлен 01.02.2013

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.