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

  • Вид работы:
    Курсовая работа (т)
  • Предмет:
    Информационное обеспечение, программирование
  • Язык:
    Русский
    ,
    Формат файла:
    MS Word
    71,35 Кб
  • Опубликовано:
    2016-02-14
Вы можете узнать стоимость помощи в написании студенческой работы.
Помощь в написании работы, которую точно примут!

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















Пояснительная записка к курсовому проекту

По дисциплине “Программирование”

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

Содержание

Введение

. Постановка задачи

. Анализ набора команд

. Выбор формата ассемблерной команды

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

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

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

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

.1 Класс Asm

.2 Класс SourceLine

7.3 Класс InfoBag

7.4 Класс ListingLine

7.5 Класс BinCom

.6 Класс DiagLine

. Отладка и тестирование программы

.1 Исходные данные

.2 Файл листинга

.3 Файл диагностики

.4 Бинарный файл

Заключение

Список литературы

Приложение

Введение

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

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

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

В данном курсовом проекте необходимо разработать транслятор упрощенного языка ассемблера. К варианту задания прилагается таблица команд ассемблера и структура ЭВМ.

1. Постановка задачи

Структура процессора

Объем оперативной памяти . 256 байт. Буферные регистры a и b предназначены для хранения операндов операций. Рабочий регистр Рез используется как регистр результата, полученного при обработке данных в АЛУ.

Коды команд:

Команды имеют длину один или два байта. Первый байт определяет код команды в соответствии с таблицей команд (биты 0-3). Следующие 4 бита предназначены для указания номера регистра, коммутируемого к буферному регистру а.

Второй байт используется для задания адреса памяти, где находится второй операнд. Если в качестве второго операнда используется регистр, то его номер хранится в младших 4-х битах второго байта команды, а старшие 4 бита не используются.

Код

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

Описание

0000

ILR регистр

Rn:=Rn+флаг переполнения

0001

NOTR регистр

Rn:= Rn +флаг переполнения

0010

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

Rn:=Rn+Память[Адрес]+ флаг переполнения

0011

CLR регистр

Rn:=0

0100

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

Rn:= Rn ∨Память[Адрес]

0101

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

Rn:= Rn ∧Память[Адрес]

0110

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

Rn:= Rn⊕Память[Адрес]

0111

JZ адрес

Переход, если результат равен 0

1001

JL адрес

Переход, если результат меньше 0

1010

JMP адрес

Безусловный переход

1011

CLF

Регистр флагов := 0

1100

DOP регистр

Перевод содержимого Rn в дополнительный код

1101

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

Rn:= Память[адрес]

1110

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

Память[адрес]:= Rn

1111

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

Сравнение содержимого Rn и Память[адрес]. Установка флагов.


Задание на курсовой проект состоит в написании учебного ассемблера с заданной таблицей команд.

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

2. Анализ набора команд

Данные в курсовом проекте команды можно подразделить на группы: арифметические команды, логические, команды загрузки, перехода, установки и команды обработки программы.

Арифметические

Код

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

Описание

0000

ILR регистр

Rn:=Rn+флаг переполнения

0001

NOTR регистр

Rn:= Rn +флаг переполнения

0010

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

Rn:=Rn+Память[Адрес]+ флаг переполнения


Установка

Код

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

Описание

0011

CLR регистр

Rn:=0

1011

CLF

Регистр флагов := 0


Переход

Код

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

Описание

0111

JZ адрес

Переход, если результат равен 0

1001

JL адрес

Переход, если результат меньше 0

1010

JMP адрес

Безусловный переход


Загрузка

Код

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

Описание

1101

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

Rn:= Память[адрес]

1110

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

Память[адрес]:= Rn


Логические

Код

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

Описание

0100

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

Rn:= Rn ∨Память[Адрес]

0101

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

Rn:= Rn ∧Память[Адрес]

0110

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

Rn:= Rn⊕Память[Адрес]


Команды имеют длину один или два байта. Первый байт определяет код команды в соответствии с таблицей команд (старшие 4 бита), а также номер регистра-операнда (младшие 4 бита), указывающего на один из РОПов процессора.

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

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

Обработка программы

Код

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

Описание

1100

DOP регистр

Перевод содержимого Rn в дополнительный код

1111

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

Сравнение содержимого Rn и Память[адрес]. Установка флагов.


3. Выбор формата ассемблерной команды

Возможные типы строк:

X - строка не определена

С - строка-комментарий

O - строка содержит ORG команду

D - строка содержит переменную или константу

E - строка, содержащая оператор завершения работы END

P - строка содержит команду микропроцессора

Положим тип строки X. Если длина массива слов исходной строки равна нулю или "", или начинается с символа ';', то тип строки - C. Если строка начинается словом "DATA", то тип строки - D. Если первое слово строки - "ORG" - тип строки - О, если "END" - E. Если в таблице команд находится мнемоника, эквивалентная первому слову в строке, то тип команды устанавливается равным P. И номер строки в таблице команд, где обнаружилось соответствие, запоминается для дальнейшего определения типа операнда.

Методика определения типа операнда

При решении данной задачи имеем строку, содержащую мнемонику, эквивалентную одной из мнемоник в таблице команд. Следовательно, известен тип строки - Р и номер строки в таблице команд. А зная строку таблицы команд, можно из неё извлечь тип операнда - строка таблицы команд её содержит в четвёртом слове.

Алгоритм формирования инфопакета

В общем случае, формирование инфопакета - это создание объекта, поля которого - строки листинга, диагностики, бинарная часть - формируются вызовом конструкторов классов ListingLine, DiagLine, BinaryBin с параметрами. Но поскольку существуют нюансы при формировании инфопакета для разных типов строк, то следует описать алгоритм создания инфопакета для каждого типа строки.

Тип строки С (метод parseComment)

В случае строки-комментария необходимо сформировать только строку листинга, которая будет содержать исходную строку, за исключением первого символа - признака комментария. Для этого конструктору класса ListingLine передаётся в качестве параметра номер строки и исходная строка преобразованная методом substring для отделения первого символа. Остальные значения параметров -1 означают отсутствие соответствующих элементов строки листинга. Строка диагностики и бинарная части (поля объекта InfoBag) устанавливаются равными null.

Тип строки О (метод setOrg)

Для строк типа О необходимо формировать строки листинга и диагностики. ORG команда не является командой микропроцессора. Она считается инструкцией ассемблеру. Поэтому бинарная часть инфопакета создается равной 1 байту. Строку диагностики для строк типа О необходимо формировать потому, что ORG команда содержит операнд, в котором возможна ошибка.

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

Тип строки D (метод setData)

Строки, хранящие данные, должны формировать "строку" бинарного файла и листинг. В случае ошибки в записи операнда, так же должен формироваться файл диагностики. Значение константы в данной задаче находится так же, как и адрес - решается задача поиска(выделения) адреса из операнда. Строка листинга формируется следующим образом: номер строки, первый байт, второй байт, исходная строка. Конструктору бинарной части инфопакета передается следующая информация: длина команды - 2, адрес команды, первый байт, второй байт. В случае ошибки в адресе операнда (поиск адреса в операнде выдал отрицательный результат), формируется следующая строка листинга: номер строки, символ ошибки, исходная строка. Бинарная часть инфопакета устанавливается равной null.

Тип строки E (метод setEnd)

Строкой типа E может являться одна единственная команда - команда END. Она не является командой микропроцессора, но бинарная часть будет равна 1 байту - FF. Команда END не содержит операндов, поэтому формирования строки диагностики на этом этапе так же происходить не будет. Строка листинга формируется просто как номер строки + исходная строка.

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

1 байт

2 байт

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

1011RRRR

----

CLF


Команды типа Р с типом операнда Z - это однобайтовые команды, старшие четыре разряда содержат код команды, остальные разряды нулевые.

Значение первого байта равно двоичному коду мнемокоманды, смещённому на четыре разряда влево.

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

Строка листинга: номер строки, адрес команды, первый байт, исходная строка. Бинарная часть: длина команды - 1, признак команды, первый байт.

Формирование строки диагностики на данном этапе не нужно, поскольку операнд в командах типа Z отсутствует. Команды типа Р с типом операнда R - это однобайтовые команды, старшие четыре разряда которого - код команды, младшие четыре разряда байта - регистр.

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

1 байт

2 байт

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

0000RRRR

----

ILR регистр

0001RRRR

----

NOTR регистр

0011RRRR

----

CLR регистр

1100RRRR

----

DOP регистр


Байт-код, соответствующий мнемонике в строке и взятый из таблицы команд в соответствующей строке сдвигается на четыре разряда влево, а младшие четыре разряда заполняются регистром. Таким образом формируется байт команды.

Строка листинга: номер строки, адрес команды, байт команды, исходная строка. Бинарная часть: длина команды - 1, признак команды, байт команды.

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

Тип строки P, тип операнда RА (метод parseRА)

1 байт

2 байт

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

0010RRRR

AAAAAAAA

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

0100RRRR

AAAAAAAA

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

0101RRRR

AAAAAAAA

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

0110RRRR

AAAAAAAA

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

1101RRRR

AAAAAAAAA

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

1110RRRR

ААААААААА

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

1111RRRR

ААААААААА

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

Команды типа Р с типом операнда 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 - двухбайтовые.

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

Метод формирует первый байт так же, как и метод parseR, а значение второго байта устанавливается равным av = setAddrValue(ops[2],Asm.pAddr). Получается, в командах типа RA старшие четыре бита - команда, затем младшие четыре разряда первого байта - первый регистр, а значение второго байта - адрес.

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

7.3 Класс InfoBag

Класс, отвечающий за создание и формирование пакета как объекта. Класс имеет следующие поля: char lineType, ListingLine listline DiagLine diagline, BinCom bincom. Поля этого класса являются объектами классов ListingLine, DiagLine, BinCom.

Класс имеет конструктор с параметрами InfoBag (ListingLine listline, DiagLine diagline, BinCom bincom). Передаваемые объекты конструктор соответственно записывает в поля объекта, тем самым формируя инфопакет с заданными в параметрах данными.

7.4 Класс ListingLine

Класс отвечает за строку листинга инфопакета. Класс содержит следующие поля: String lineNo - номер строки, String comAddress - адрес размещения команды, String byteOne - первый байт комады, String byteTwo - второй байт команды, errMark - метка ошибки, String srcLine - копия исходной строки.

Имеет конструктор без параметров, который инициализирует объект с пустыми значениями полей класса.

Так же имеет конструктор с параметрами ListingLine( int lno, int ad, int k1, int k2, String err, String line). Полю lineNo присваивается значение lno, с использованием формата: действительное число с четырьмя знаками. Если параметр ad<0, полю comAddress присваивается значение " ххх ". В противном случае в переменную comAddress записывается отформатированное значение ad. Далее, если значение переменных k1 и k2 больше нуля, то переменные byteOne и byteTwo заполняются этими значениями соответственно. Если длина какого-то параметра будет меньше нуля, то соответственное поле заполнится “xx ” строкой. Значение поля errMark устанавливается равным первому символу строки err, передаваемой в качестве параметра. Переменной srcLine присваивается значение переменной line.

Класс содержит перегруженный метод toString, который формирует и возвращает String-представление объекта класса ListingLine. Метод возвращает строку, состоящую из последовательно соединенных полей объекта.

7.5 Класс BinCom

Класс отвечает за формирование байтов бинарного файла. Класс имеет поля int len - длина команды в байтах, int addr - адрес первого байта команды в памяти, byte1, byte2 - первый и второй байты команды, int p - признак команды, или директива

Класс содержит конструктор без параметров BinCom() и конструктор с параметрами (int l, int pd, int a, byte b1, byte b2). Параметры последнего конструктора записываются в соответствующие поля объекта, тем самым создавая объект с заданными параметрами.

7.6 Класс DiagLine

Класс, описывающий строку диагностики инфопакета.

Класс инициализирует статический массив строк-ошибок ErrorMess[]. Имеет одно единственное поле: String Line.

В классе существует два конструктора - пустой DiagLine() и с параметрами DiagLine (int ln, String msg). Передаваемые параметры в соответствии с форматом ("%03d", ln) записываются в поле line.

В классе определён перегруженный метод toString, возвращающий String-представление объекта класса DiagLine. В качестве результата метод возвращает строку line.

8. Отладка и тестирования программы

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

8.1 Исходные данные ( файл Src.txt)

ORG 10H;R0,25H;R0,26H;R10,27H;

NOTR R15,29H;один два три31H;один два три; ORG 25H;30H;31H;0H;245H;24;R0,45H;5,39H;R15,45;

8.2 Файл листинга (List.txt)

Листинг

1 010 хх хх ORG 10H;

2 010 d0 25 LOAD R0,25H;

3 012 20 26 ADR R0,26H;

4 014 ea 27 SAVE R10,27H;

5 016 1f хх NOTR R15,29H;один два три

6 017 70 31 JZ 31H;один два три

7 019 b0 хх CLF ;

8 025 хх хх ORG 25H;

9 025 30 хх DATA 30H;

10 026 31 хх DATA 31H;

11 027 00 хх DATA 0H;

13 ххх хх хх -DaTA 245H;

14 ххх хх хх -DATA 24;

15 ххх хх хх -LOD R0,45H;

16 ххх хх хх -ADR 5,39H;

17 ххх хх хх -SAVE R15,45

19 ххх ff хх END;

.3 Файл диагностики(Diag.txt)

Диагностика

DaTA 245H;

неверная мнемоника

DATA 24;

неправильно задан регистр(адрес)

LOD R0,45H;

неверная мнемоника

ADR 5,39H;

Первый операнд: неправильно задан регистр(адрес)

SAVE R15,45

Второй операнд: неправильно задан регистр(адрес)

.4 Файл с объектным двоичным кодом(binary.bin)


Данная последовательность команд проверяет правильность работы всех ветвей программы, связанных с обработкой правильных команд (методы parseLine, parseR, parseZ, parseRA, parseA, setAddrValue, setRegValue, findCom класса SourceLine, а так же классы InfoBag, ListingLine, DiagLine, BinCom и Asm).

Заключение

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

Список литературы

1. Ноутон П. Java 2: [пер. с англ.]/П.Ноутон, Г.Шилдт. - СПб.: БХВ-Петербург, 2014. - 1072 с.

Приложение

Текст программы

Класс Asmjava.io.*;java.util.regex.*;class Asm {

static int acom = 0; //адрес команды

static BufferedReader src = null; //поток для исходной программы

static PrintWriter list = null; //поток для листинга

static PrintWriter diag = null; //поток для диагностики

static RandomAccessFile bin = null; //поток для двоичных команд

static Pattern pAddr; //скомпилированное рег.выр. для адреса

static Pattern pReg; //скомпилированное рег.выр. для регистра

static String[ ] PRCOMTAB = { //команды микроЭВМ

"ILR 0000 1 P R",

"NOTR 0001 1 P R",

"ADR 0010 2 P RA",

"CLR 0011 1 P R",

"ONR 0100 2 P RA",

"ANR 0101 2 P RA",

"XNR 0110 2 P RA",

"JZ 0111 2 P A",

"JL 1001 2 P A",

"JMP 1010 2 P A",

"CLF 1011 1 P Z",

"DOP 1100 1 P R",

"LOAD 1101 2 P RA",

"SAVE 1110 2 P RA",

"CMP 1111 2 P RA",

"ORG XXXX X O ",

"DATA XXXX 1 D",

"END XXXX X E"

};

static String[ ] prCom; //мнемоника команд микроЭВМ -1-й столбец табл. 1

static { //статический инициализатор таблицы prCom

pAddr = Pattern.compile ( "^[0-9a-fA-F]{1,2}[hH]$" );

pReg = Pattern.compile ( "^[Rr](([0-9])|([1][0-5]))$" );

prCom = new String[PRCOMTAB.length];

for (int i = 0; i < PRCOMTAB.length; i++) {

prCom[i] = PRCOMTAB[i].substring(0, PRCOMTAB [ i ].indexOf(' '));

}

}

public static void main(String[ ] args) throws IOException {

String srcFile = "Src.txt"; //исходная программа

String listFile = "List.txt"; //листинг

String binFile = "binary.bin"; //двоичный код

String diagFile = "Diag.txt"; //диагностика

String line; //строка исходного файла

int num = 0; //номер строки файла

SourceLine sl;

ListingLine ll;

DiagLine dl;

BinCom bc;

//действия по открытию файлов

try { //если файлы нельзя открыть - исключение и окончание работы

src = new BufferedReader(new FileReader(srcFile));

list = new PrintWriter(listFile);

list.println("Листинг");

diag = new PrintWriter(diagFile);

diag.println("Диагностика");

bin = new RandomAccessFile(binFile, "rw");

ll = new ListingLine();

 dl = new DiagLine();

bc = new BinCom();

InfoBag infobag=null;

while (( line = src.readLine()) != null ) { num++; //прочли строку

sl = new SourceLine ( line, num );

try {

infobag = sl.parseLine(sl.words); //обработка строки

list.println (infobag.listline);

if (infobag.diagline != null )

diag.println(infobag.diagline); ( infobag.lineType ) {

case 'O': Asm.acom = infobag.bincom.addr;

bin.writeByte ( infobag.bincom.p );

bin.writeByte ( infobag.bincom.addr ); break;

case 'D': bin.writeByte ( infobag.bincom.p );

bin.writeByte (infobag.bincom.byte1);

Asm.acom+= infobag.bincom.len; break;

case 'P': bin.writeByte ( infobag.bincom.p );

bin.writeByte ( infobag.bincom.byte1 );

if (infobag.bincom.len == 2) { //если требуется второй байт

bin.writeByte ( infobag.bincom.p );

bin.writeByte ( infobag.bincom.byte2 );

}

Asm.acom+= infobag.bincom.len; break;

case 'E': bin.writeByte ( infobag.bincom.p );

default:

}

}

catch (Exception e) { }

}//while

}//try

finally { //закрытие потоков

if ( src != null) { src.close ( ); }

if ( list != null) { list.close ( ); }

if ( diag != null) { diag.close ( ); }

if (bin !=null) {bin.close( ); }

}//finally

}

}

Класс SourceLinejava.io.*;java.util.*;java.lang.*;java.util.regex.*;class SourceLine { // Класс : строка исходной программы

String sourceLine; //исходная строка, заполняется конструктором

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

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

int lineNumber; //номер строки

char lineType; //C-комментарий, A,O,D,E-команды ассемблера,

//P-команда процессора, X - неизвестный тип

int nAsm; //номер команды в таблице команд ассемблера

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

public SourceLine(String l, int n) { // конструктор

sourceLine = new String(l); // Задается сама строка

lineNumber = n; // и ее номер,

myLine = sourceLine.trim(); // удаляются пробелы слева и справа,

words = myLine.split("(\\s+)|[,;]"); // строка разбивается на слова

}

public InfoBag parseLine(String[ ] wo) { //wo - массив слов строки

InfoBag info = null; DiagLine dil = null; ListingLine lil = null;

lineType = 'X'; //а вдруг определить не удастся

String[ ] ww = null; //для частей из таблицы команд

if ( wo.length == 0) lineType = 'C';//пустая строка

if ( wo [ 0 ].equals("") ) lineType = 'C';

if ( wo [ 0 ].charAt ( 0 ) == ';') lineType = 'C';

else if ((nProc = findCom(wo[0], Asm.prCom)) >= 0) //поиск команды в та

{ ww = Asm.PRCOMTAB [ nProc ].split ( "\\s+" ) ;

lineType = ww [ 3 ].charAt ( 0 );//поле с номером 3 в PRCOMTAB - тип

}

switch (lineType) {//обработка команды согласно ее типу

case 'C': info = parseComment (); info.lineType = 'C'; break;

case 'O': info = setOrg ( wo ); info.lineType = 'O'; break;

case 'D': info = setData( wo ); info.lineType = 'D'; break;

case 'E': info = setEnd( wo ); info.lineType = 'E'; break;

case 'P': //команды микроЭВМ

String kod = ww [ 1 ]; //поле 1 в PRCOMTAB - код команды

int binaryKod = Integer.parseInt ( kod, 2 ); //получен код операц

String format = ww [ 4 ]; //выбор поля 4 - формата команды

if (format.equals ("RA" )) info = parseRA ( wo, binaryKod );

if (format.equals ( "Z" )) info = parseZ ( wo, binaryKod);

if (format.equals ( "A" )) info = parseA ( wo, binaryKod);

if (format.equals ( "R" )) info = parseR ( wo, binaryKod);

info.lineType = 'P'; break; //строка - команда микроЭВМ

default: {

dil = new DiagLine(lineNumber, sourceLine + "\n " + DiagLine.ErrorMess[1]);

lil = new ListingLine(lineNumber, -1, -1, -1,"-", sourceLine);

info = new InfoBag(lil,dil,null); info.lineType = 'X';

}

}

return info;

}InfoBag parseComment(){

return new InfoBag (

new ListingLine ( lineNumber, -1, -1, -1, " ", sourceLine), null, null );

}int findCom ( String w, String [ ] com ) { //прямой поиск w в com

for ( int i = 0; i < com.length; i++ ) {

if ( w.equals( com [ i ] ) )

return i;

}

return -1;

}

private InfoBag setOrg ( String[ ] ops) { //параметр - массив слов строки

DiagLine dil = null;

ListingLine lil = null;

BinCom bic = null;

int av = -3;

if (ops.length > 1) av = setAddrValue ( ops[1], Asm.pAddr );

if (av>= 0) {

lil = new ListingLine ( lineNumber, av, -1, -1," ", sourceLine);

bic = new BinCom(1, 1, av,(byte)0,(byte)0);

}

else {

lil = new ListingLine( lineNumber, -1, -1, -1, "-", sourceLine);

dil = new DiagLine( lineNumber, sourceLine + "\n " + DiagLine.ErrorMess[-av]);

}

return new InfoBag ( lil, dil, bic);

}InfoBag setData(String[ ] ops){

DiagLine dil = null;

ListingLine lil = null;

BinCom bic = null;

int av = -3;

if (ops.length > 1) av = setAddrValue ( ops[ 1 ], Asm.pAddr );

if (av>= 0) {

lil = new ListingLine ( lineNumber, Asm.acom, av, -1, " ", sourceLine );

bic = new BinCom (1, 2, Asm.acom, (byte) av, (byte) 0);

}

else {

lil = new ListingLine ( lineNumber, -1, -1, -1, "-", sourceLine);

dil = new DiagLine ( lineNumber, sourceLine + "\n " + DiagLine.ErrorMess[-av]);

}

return new InfoBag ( lil, dil, bic);InfoBag setEnd(String [] ops) {

DiagLine dil = null;

ListingLine lil = null;

BinCom bic = null;

int k=(7<<5)|(7<<2)|3;

return new InfoBag ( lil = new ListingLine ( lineNumber, -1, k, -1, " ", sourceLine),

null,

bic = new BinCom (1, k, Asm.acom, (byte)0, (byte) 0) );

}InfoBag parseRA(String [ ] ops, int bk ) {//формат RA - регистр, адрес

int k = bk; int rv, av;

DiagLine dil = null;

ListingLine lil = null;

BinCom bic = null;

if ( ops.length > 1) { rv = setRegValue(ops[1], Asm.pReg);

}

else { rv = -3; } //операнда нет

k = (bk << 4) | ( rv | 0 );

if (ops.length > 2) { av = setAddrValue(ops[2],Asm.pAddr);

}

else { av = -3; } //операнда нет

if ((rv>= 0) && (av>= 0)) {

lil = new ListingLine ( lineNumber, Asm.acom, k, av, " ",sourceLine);

bic = new BinCom ( 2, 2, Asm.acom, (byte)k, (byte)av);

}

else { //ошибка в 1-м или 2-м операнде

String xx = new String();

String newString=new String();

if (rv<0) {

xx+= new String("Первый операнд: " + DiagLine.ErrorMess[-rv]);

newString="\n";//есть первая строка

}

if (av<0) {

xx+=newString;

xx+= new String("Второй операнд: " + DiagLine.ErrorMess[-av]);

}

lil = new ListingLine( lineNumber, -1, -1, -1, "-",sourceLine);

dil = new DiagLine( lineNumber, sourceLine + "\n" + xx);

}

return new InfoBag( lil, dil, bic);

}InfoBag parseA(String [ ] ops, int bk ) {//формат A - адрес

int k = bk; int av;

DiagLine dil = null;

ListingLine lil = null;

BinCom bic = null;

if ( ops.length > 1) { av = setAddrValue(ops[1], Asm.pAddr);

}

else { av = -3; } //операнда нет

k = (bk << 4);

if (av>= 0) {

lil = new ListingLine ( lineNumber, Asm.acom, k, av, " ",sourceLine);

bic = new BinCom ( 2, 2, Asm.acom, (byte)k, (byte)av);

}

else { //ошибка в 1-м или 2-м операнде

String xx = new String();String newString=new String();

xx+= new String ("Oперанд: " + DiagLine.ErrorMess [ -av ] );

lil = new ListingLine( lineNumber, -1, -1, -1, "-",sourceLine);

dil = new DiagLine( lineNumber, sourceLine + "\n" + xx);

}

return new InfoBag( lil, dil, bic);

}InfoBag parseZ (String[ ] ops, int bk ) {//формат Z - без операндов

DiagLine dil = null;

ListingLine lil = null;

BinCom bic = null;

int k = (bk << 4); // 4 бита - код операции,

lil = new ListingLine(lineNumber, Asm.acom, k, -1, " ",sourceLine);

bic=new BinCom ( 1, 2, Asm.acom, ( byte ) k,(byte)0);

return new InfoBag ( lil, dil, bic );

}InfoBag parseR ( String [ ] ops, int bk ) { //формат R

int k=bk; int rv;

DiagLine dil = null;

ListingLine lil = null;

BinCom bic = null;

if (ops.length > 1) { rv = setRegValue(ops[1], Asm.pReg);

}

else { rv = -3;}

k = (bk << 4)|(rv | 0);

if ( rv>= 0 ) { // ошибок в операнде нет

lil = new ListingLine(lineNumber, Asm.acom, k, -1, " ",sourceLine);

bic=new BinCom ( 1, 2, Asm.acom, ( byte ) k, ( byte )0);

}

else { // в операнде есть ошибки

String xx =new String ("Первый операнд: "+DiagLine.ErrorMess [-rv] );

lil = new ListingLine ( lineNumber, -1, -1, -1, "-",sourceLine );

dil = new DiagLine ( lineNumber, sourceLine + "\n" + xx ) ;

}

return new InfoBag ( lil, dil, bic );

}int setRegValue(String w,Pattern pr) {// w - слово, содержащее операнд-регистр

if (( w == null ) || ( w.length()==0 )) { val= -3;

}

else {

if ( pr.matcher(w).matches( ) ) {

val = Integer.parseInt ( w.replaceAll("[Rr]",""));

val = (val | 0);

}

else { val = -2; }

}

return val;

}int setAddrValue( String w,Pattern pr) {

int val = 0;

if ((w == null) || (w.length() == 0)) { val= -3;

}

else {

if ( pr.matcher(w).matches ( ) ) {

val = Integer.parseInt ( w.substring ( 0, w.length( ) - 1), 16);

}

else { val= -2; }

}

return val;

}

}

Класс InfoBag

public class InfoBag { //информационный пакет

char lineType; //тип строки в исходном тексте

ListingLine listline; //строка листинга

DiagLine diagline; //строка диагностики

BinCom bincom; //двоичный код, соответствующий строке

public InfoBag (ListingLine listline, DiagLine diagline ,BinCom bincom) {

this.listline = listline;

this.diagline = diagline;

this.bincom = bincom;

}

}

Класс ListingLineclass ListingLine {

String lineNo; //номер строки

String comAddress; //адрес размещения кода команды

String byteOne; //первый байт команды

String byteTwo; //второй байт команды

String errMark; // ‘’-‘’ отметка строки с ошибкой

String srcLine; //копия исходной строки

public ListingLine( ) { lineNo = new String(); byteOne = new String();

byteTwo = new String(); comAddress = new String();

srcLine = new String();

}

public ListingLine(int lno ,int ad, int k1, int k2, String err, String line){

lineNo = new String(String.format("%4d ", lno));

if (ad<0) comAddress = new String(String.format("ххх "));

else comAddress = new String(String.format("%03x ",ad));

if (k1<0 ) byteOne = new String(String.format("хх "));

else byteOne = new String(String.format("%02x ",k1));

if (k2<0 ) byteTwo = new String(String.format("хх "));

else byteTwo = new String(String.format("%02x ",k2));

errMark = err.substring(0, 1);

srcLine = line;String toString() {

return new String(lineNo+comAddress+byteOne+byteTwo+errMark+srcLine);

}

}

Класс BinComclass BinCom {

int len;

int addr;

byte byte1, byte2;

int p;

public BinCom ( ) {

len= addr= byte1= byte2=(byte)0;

}

public BinCom ( int l, int pd, int a, byte b1,byte b2 ) {

len = l; addr = a; p=pd;

byte1 = b1; byte2 = b2;

}

}

Класс DiagLineclass DiagLine {

public static String[ ] ErrorMess={

"все хорошо", //0

"неверная мнемоника", //-1

"неправильно задан операнд(адрес)", //-2

"операнд отсутствует" //-3

};

String lineNo;

String ms;

public DiagLine ( ) {

lineNo = new String();

ms = new String();

}

public DiagLine ( int ln, String msg ) {

lineNo = new String ( String.format ( "%03d", ln) ) ;

ms = msg;

}

public String toString(){

return new String ( lineNo+" "+ms);

}

}

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

 

Не нашли материал для своей работы?
Поможем написать уникальную работу
Без плагиата!