Материал: Моделирование вычислительной системы. Ассемблерная часть

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

Команды типа Р с типом операнда RА - двухбайтовые команды. Поскольку длина самой команды - четыре бита, а длина операнда - четыре бита, то необходимо использовать минимум два байта для записи такой команды. Распределим информацию в байтах таким образом: старшие четыре разряда первого байта - бинарный код команды, младшие четыре разряда первого байта - первый операнд, второй байт - операнд адрес.

Первые байт формируется точно так же, как и в случае типа операнда R. Значение второго байта заполняется адресом. Строка листинга: номер строки, адрес команды, первый байт, второй байт, исходная строка. Бинарная "строка": длина команды - 2, признак команды, первый байт, второй байт.

Для данного типа строки возможны две ошибки - ошибка в первом операнде и ошибка во втором операнде. Если значение операнда отрицательно, формируется строка диагностики: "Первый"/"Второй" +" операнд:" + краткое описание типа ошибки.

Тип строки P, тип операнда A (метод parseA)

1 байт

2 байт

Мнемокод и операнд

0111----

AAAAAAAA

JZ адрес

1001----

AAAAAAAA

JL адрес

1010----

AAAAAAAA

JMP адрес


Строки типа Р с типом операнда A являются двухбайтовыми командами. Старшие четыре разряда, как и в остальных командах типа Р, содержат байт-код команды, младшие четыре разряда будут являться нулями. Остальные восемь разрядов операнда адреса будут храниться во втором байте.

Первый байт формируется как и в предыдущих случаях - поразрядным сдвигом байт-кода команды на четыре. Строка листинга формируется следующим образом: номер строки, адрес команды, первый байт, второй байт, исходная строка. Бинарная "строка": Длина команды - 2, первый байт, второй байт.

В случае, если допущена ошибка в записи операнда, формируется строка листинга: номер строки, признак ошибки и исходная строка. Строка диагностики: номер строки, исходная строка, символ перехода на новую и краткое описание типа ошибки. Бинарная часть инфопакета - null.

Алгоритм поиска(выделения) адреса

Задача поиска адреса должна давать следующие результаты: если операнд написан верно - его значение, если не верно - код ошибки (отрицательное число).

Методу в качестве параметров передаётся слово-операнд из исходной строки и шаблон записи адреса. Если переданное слово пусто (null, или длина слова равна 0), то результат -3(операнд отсутствует). Если слово не удовлетворяет шаблону, то результат равен -1 (номер ошибки, соответствующий неверной мнемонике). Если слово удовлетворяет шаблону, производится идентификация кода - считывание признака системы счисления. Если на этапе преобразования возникнет исключение (Exception), то результатом будет -2(неверно задан регист(адрес)). Если ошибки не возникло, метод возвращает значение операнда.

Алгоритм поиска(выделения) регистра

Задача аналогичная задаче поиска адреса за исключением положения, касающегося непосредственно поиска значения регистра. Значения регистров лежат в интервале от 0 до 15. из исходной строки выделяется непосредственно значение регистра, и если он задан числом - возвращается это число. Принцип формирования ошибок типа -1 и -3 аналогичен принципу в задаче поиска адреса. Формирование ошибки типа два происходит в случае, если операнд не является числом 0-15.

Попробуем описать алгоритм работы программы опустившись до уровня решения подзадач.

Первым шагом алгоритма является создание потоков считывания и записи. Далее считывается строка если она не равна нулю, выполняется её обработка: решается задача определения типа строки. Если тип строки C, O, D, E - решается задача формирования инфопакета для соответствующего типа строки. Если тип строки P - находится тип операнда команды и решается соответствующая задача формирования инфопакета. Сформированные строки инфопакета выводятся в соответствующие файлы. Считывается следующая строка. И так до тех пор, пока не будет обработана строка типа E или строка не будет пустой (конец текстового файла). Потоки считывания и записи закрываются.

4. Описание входных и выходных данных

Входные данные:

Текстовый файл, содержащий программу на ассемблере. Команды в программе имеют длину 1 или 2 байта. Биты 4-7 первого байта содержат код команды в соответствии с таблицей команд. Биты 0-3 и второй байт используются для задания адреса памяти, где находится константа или операнд.

Все операции производятся над операндами, находящимися в памяти или стеке. Результат может быть сохранен в памяти или стеке. Каждая строка должна содержать не более одной команды. Мнемокод отделяется от операнда последовательностью пробелов. Таблица допустимых команд:

Код

Мнемокод и операнды

0000

ILR регистр

0001

NOTR регистр

0010

ADR регистр,память

0011

CLR регистр

0100

ONR регистр, адрес

0101

ANR регистр, адрес

0110

XNR регистр, адрес

0111

JZ адрес

1001

JL адрес

1010

JMP адрес

1011

CLF

1100

DOP регистр

1101

LOADрегистр,адрес

1110

SAVE регистр,адрес

1111

CMP регистр, адрес


В программе имеет значение регистр символа - он обязательно должен быть верхним.

Программа должна выполнять преобразование текстового файла в двоичный код (т.е. код команды и код адреса нахождения операнда).

Выходные данные:

При выполнении программы формируются 3 файла:

.        Бинарный файл, который получается в результате трансляции команд данного текстового файла;

.        Текстовый файл - файл-листинг, который содержит исходный текст, его кодировку и результаты трансляции.

.        Файл диагностики. В этот файл выводятся сообщения об ошибках трансляции:

ошибка в написании имени команды

ошибка в написании операндов

отсутствие операндов

При выявлении ошибки формирование объектного файла невозможно и выполнение программы прекращается, а в файле диагностики выводится описание ошибки.

5. Анализ возможных ошибок

В результате ассемблирования может возникнуть ряд ошибок:

Неверные разделители(Отличный от запятой при разделении операндов, от пробела или Таb, при разделении мнемоники и операнда или операндов)

Неверная мнемоника команды, или её отсутствие

Несуществующий адрес

Отсутствие операнда у команды

Неверное написание операнда

Комментарии не отделены

6. Разработка программы

Программа имеет некоторые ограничения:-в каждой строке записывается только одна команда процессора;

команда содержит мнемонику операции, за мнемоникой следуют операнды;

после операндов можно расположить комментарий

если операнды есть, между мнемоникой и операндами должен быть по крайней мере один пробел;

комментарий начинается знаком «;», или отделяется пробелом;

7. Описание программы

.1 Класс Asm

Является главным классом программы. Содержит инициализацию таблицы команд процессора, записи операндов-регистров и операндов-адресов, констант, потоков считывания и записи, переменной адреса команды acom. Имеет главный метод main, который нужно выполнить, чтобы запустить программу.

В качестве потока считывания исходного текста src.txt используется класс BufferedReader (FileReader). Для потоков записи файлов листинга и диагностики используется класс PrintWriter. Для формирования бинарного файла используется класс RandomAccessFile.

Массив String[] PRCOMTAB формируется в соответствии с таблицей команд процессора. Каждому элементу массива соответствует команда из таблицы команд. Команды не повторяются, каждая команда имеет уникальный мнемокод и двоичный код. Формат строки массива PRCOMTAB: мнемокод, двоичный код, длина команды, тип команды, тип операнда. Каждый элемент в строке должен быть отделён от соседнего пробелом.

Инициализация шаблонов записи операндов-адресов и операндов-регистров. Операнд адрес - это слово, которое в случае двоичного кода может иметь не более 8-ми битов. Может содержать любые символы шестнадцатеричной системы счисления (0-15) и обязательно заканчиваться на один из символов h,H.

Операнд-регистр - длиной не менее и не более трех символов .Первый символ - признак регистра, второй и третий символ - номер регистра. Для 16 регистров достаточно двух символов, чтобы указать каждый регистр. Регистр должен удовлетворять такому регулярному выражению: "^[Rr](([0-9])|([1][0-5]))$". Это значит что регистр должен начинаться с символов R или r и заканчиваться цифрой от 0 до 15.

Метод main(String[] args) Является главным исполняемым методом. Создаёт потоки считывания и записи, производит считывание строк, вызывает метод обработки строки parseLine и выполняет вывод инфопакета, сформированного в процессе обработки строки, в файлы листинга и диагностики. После считывания строки, формирования инфопакета и вывода строки диагностики, в зависимости от типа строки lineType, выполняет следующие действия: если тип строки О (ORG-адрес) - устанавливает значение acom, равное значению адреса, хранящемуся в сформированном инфопакете, в его бинарной части; если тип команды D (DATA) - записывает в бинарный файл адрес команды, выводит значение первого и второго байта, увеличивает acom на bincom.len (длину команды); P ( команда процессора) - выводит адрес команды, значение первого байта, и если команда двухбайтовая - выводит второй байт. Весь текст метода, начиная с считывания строки заключен в блок try, и в случае возникновения исключения, все потоки будут закрыты, а выполнение программы остановлено.

7.2 Класс SourceLine

ассемблер транслятор двоичный код

Содержит основные методы обработки исходной строки: parseLine, parseComment, setOrg, setData, setEnd, parseRА, parseA, parseR, parseZ; а так же вспомогательные: setAddrValue, setRegValue, findCom. Основные методы в качестве результата возвращающают инфопакет, вспомогательные - формируют результаты вычисления подфункций.

Класс имеет следующие поля:

String sourceLine - исходная строка, формируется конструктором - считывается из файла Src.txt.

String myLine - исходная строка без пробелов слева и справа.

String[] words - части строки - слова.

int lineNumber - номер строки.

char lineType - тип строки.

int nProc - номер команды в таблице команд микроЭВМ

Метод parseComment(String line)

В качестве параметра методу передаётся исходная строка. Метод формирует инфопакет, бинарная и диагностическая части которого равну null. Строка листинга формируется следующим образом - конструктору ListingLine передается следующий набор параметров : (-1, -1, -1, -1, " ", line.substring(1,line.length())). Последний параметр - это строка без первого символа, т.е. без символа ";".

В качестве результата метод возвращает сформированный инфопакет.

Метод parseLine(String[] wo)

Метод определяет тип строки (X,C,O,D,E,P). Переменной lineType, в результате выполнения метода присваивается одно из этих значений в зависимости от содержания исходной строки.

В случае, если строка имеет тип P, переменной kod присваивается значение двоичного кода этой команды и в переменную format записывается 4-ое поле PRCOMTAB - формат команды (RA,R,A,Z). Каждому формату команды соответствует свой метод обработки строки. Для строки RA будет выполняться метод parserRA, для R - parseR. Для данной структуры метод parseRA не нужен. Но т.к. PRCOMTAB содержит команды формата A, необходимо определить метод parseA().

В случае, если тип строки X, формируется инфопакет ошибки.

Метод findCom(String w, String[] com)  является вспомогательным служебным методом. Методу в качестве параметров передаётся строка w (первое "слово" исходной строки) и массив строк com (таблица мнемоник команд). Прямым поиском сравнивается w и элементы массива com. В качестве результата метод возвращает значение номера элемента массива com, которому соответствует w. Если такого соответствия не обнаружено, метод возвращает -1.

Метод setRegValue(String w, Pattern pr)

Так же является вспомогательным методом.

Методу в качестве параметра передается "слово" w, содержащее операнд регистр, вида R1 или r14. Метод проверяет длину строки w на наличие в нём символов (операнда). Если символов нет, переменной val присваивается значение -3, и при дальнейшей проверке этой переменной формируется инфопакет ошибки. Если строка w не удовлетворяет правилам записи строки, хранящиеся в Pattern pr, значение val устанавливается равным -2, что означает ошибку с кодом -2, т.е. неверная мнемоника.

Если значение слова больше нуля, и слово удовлетворяет правилам записи операнда-регистра, выполняется следующее: в переменную val записывается значение w, переведённое из той системы счисления, которое указано конечным символом слова w. Метод возвращает значение val.Если меньше возвращает -3.

Метод setAddrValue(String w, Pattern pr) повторяет метод setRegValue.

Метод setOrg(String[] ops)

В качестве параметра методу передается массив слов исходной строки. Метод формирует инфопакет. Строка листинга инфопакета формируется конструктором ListingLine с набором параметров (lineNumber, Asm.acom, av, -1," ", sourceLine). Строка бинарного файла создается c 1 байтом.

Метод setData(String[] ops)

В качестве параметра методу передается массив слов исходной строки. Метод формирует инфопакет. Строка листинга инфопакета формируется конструктором ListingLine с набором параметров ( lineNumber, Asm.acom, av, -1, " ", sourceLine ). Строка бинарного файла создается c 1 байтом. Метод setEnd( ) возвращает инфопакет со строкой листинга, строкой бинарного файла с 1 байтом. Метод parseZ(String[] ops, int bk) Метод возвращает инфопакет, содержащий информацию об обработке команды типа Z (команда типа Z - строка, не содержащая операндов).

В случае адекватных данных метод присваивает значению k, значение двоичного представления команды, которое передаётся ему в качестве параметра bk. Метод выполняет операцию поразрядного сдвига на четыре влево.

Метод parseR(String[] ops, int bk)

Почти аналогичен методу parseZ, за одним исключением. После формирования переменной k, равной bk и операции сдвига влево на четыре разряда, к переменной применяется операция порязрядного сложения переменной rv, значение которой устанавливается методом setRegValue(ops[1], Asm.pReg).

Конструктору бинарной строки передает один, первый байт.

Метод parseA(String[] ops, int bk)

Обрабатывает строку типа A. Строка типа А содержит команду операнд-адрес. Метод формирует переменную k так же, как и метод parseZ, только значением второго байта берет av, предварительно сформированное методом setAddrValue(ops[1], Asm.pAddr). Команды типа A - двухбайтовые.