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

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

Метод 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 {