Проектирование компилятора

 

Цель работы


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

Расчет варианта задания производится по формуле:

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


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

Получили следующие команды: NEG, JE, ADC, SHL, INC.

Задание: Для заданного набора команд разработать, отладить и протестировать программу - компилятор.


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

.asm является программой для нахождения разницы между двумя большими числами (32 разряда). Использует все заданные команды, JE, NEG, SHL, INC и кроме того команды MOV, INT.segment; сегмент данныхdw 1001h; a1, a2, b1, b2 - исходные данныеdw 10h; с1, с2 - результат

b1 dw 0abcdhdw 20h

c1 dw 0dw 0dw 4c00h; 4ch - ф-ция выхода, 00h - код возврата

datas endssegment:cs:codes, ds:datasax, datasds, axax, a1;

movdx, a2; загрузить данные вbx, b1; регистрыcx, b2;ax;m1;dx; инверсия первого числа

m1:neg dx;di, c1; 0 -> бит CF

shldi, 1;ax, bx; сложить младшие частиdx, cx; сложить старшие части и бит CFm2c1, ax; сохранить:movc2, dx; результатax, vix; завершение

int21h; программыendsstart

Находится разница между двумя 32-разрядными операндами. Второй операнд инвертируется и складывается с первым. Операнды и результат располагаются в памяти. Базовый набор команд дополнен командами: MOV и INT, директивой - DW.

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


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

: Сложение с переносом

Операция: Обычно используется при сложении многословных величин для учета бита переполнения в последующих фазах операции. Если флаг CF установлен в 1, то команда ADC сначала прибавляет 1 к операнду 1. Команда всегда прибавляет операнд 2 к операнду 1, аналогично команде ADD.

Флаги: Команда воздействует на флаги AF, CF, OF, PF, SF и ZF.

Объектный код (три формата): Регистр плюс регистр или память:|000100dw|modregr/m|.: Прерывание

Операция: Прерывает выполнение программы и передает управление по одному из 256 адресов (векторов прерывания). Команда INT выполняет следующее: 1) уменьшает значение SP на 2 и заносит в стек флаговый регистр, сбрасывает флаги IF и TF; 2) уменьшает значение SP на 2 и заносит регистр CS в стек, старшее слово из вектора прерывания помещает в регистр CS; 3) уменьшает значение SP на 2 и заносит регистр IP в стек, младшее слово из вектора прерывания помещает в регистр IP.

Флаги: Команда воздействует на флаги IF и TF.

Объектный код: |1100110v|-type-| (если v = 0, то type = 3).const: Прерывание

Операция: Прерывает выполнение программы и передаёт управление по одному из 256 адресов (векторов прерывания).

Объектный код: |11001101|-type-|./JZ: Переход по «равно» или по «нулю»

Операция: Используется после проверки знаковых или беззнаковых данных для передачи управления по другому адресу. Если флаг ZF равен единице (нулевое состояние), то команда прибавляет к регистру IP значение операнда (относительное смещение) и выполняет таким образом переход.

Флаги: Не меняются.

Объектный код: |01110100|-disp-|: Пересылка данных

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

Флаги: Не меняются.

Объектный код (семь форматов):

Регистр/память в/из регистр:

|100010dw|modregr/m|

Непосредственное значение в регистр:

|1011wreg|-data-|data если w=1|

Память в регистр AX (AL):

|1010000w|addr-low|addr-high|

Регистр AX (AL) в память:

|1010001w|addr-low|addr-high|

Регистр/память в сегментный регистр:

|10001110|mod0sgr/m| (sg - сегментный регистр): Изменение знака числа

Операция: Меняет двоичное значение из положительного в отрицательное и из отрицательного в положительное. Команда NEG вычисляет двоичное дополнение от указанного операнда: вычитает операнд из нуля и прибавляет единицу. Операндом может быть байт или слово в регистре или в памяти.

Флаги: Команда воздействует на флаги AF, CF, OF, PF, SF и ZF.

Объектный код: |1111011w|mod011r/m|: Сдвиг влево или вправо

Операция: Выполняет сдвиг битов влево.

Флаги: Команда воздействует на флаги CF, OF, PF, SF и ZF (флаг AF не определен).

Объектный код: SAL/SHL: |110100cw|mod100r/m|.


3. Алгоритмы и таблицы компилятора


Компилятор, разрабатываемый в данной курсовой, является двух-проходным. Он использует следующие системные таблицы.- таблица мнемокодов. Содержит следующие поля: name - мнемокод. SYMTAB - таблица символических имён. Содержит следующие поля: name - символическое имя; sgm - сегмент, в котором оно объявлено; dsp - смещение в сегменте. SEGTAB - таблица сегментов. Содержит следующие поля: name - имя сегмента; len - длина сегмента в байтах.

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

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

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

Составление объектного файла.

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


4. Исходный текст программы компилятора


#include<stdio.h>;

#include<string.h>;

#include<stdlib.h>;

#include<ctype.h>;

#include<conio.h>;

#include<io.h>;i, c, npr, seg, cnt, pmdf, psym, stk[80], pole[4] [8];

//npr - номер прохода, seg - номер сегмента, cnt - счетчик размещения команд

//pmdf - указатель на конец записи модификатора, psym - указатель на конец

// таблицы меток, stk - сюда считывается строка, pole - поля полученные из

// считанной строки.optab[8] [4]={{«mov»}, {«neg»}, {«je\0»}, {«inc»}, // таблица

{«shl»}, {«adc»}, {«int»}, {«dw\0»}}, // мнемокодов[8] [3]={{«ax»}, {«cx»}, {«dx»}, {«bx»}, // таблицы обозначений

{«sp»}, {«bp»}, {«si»}, {«di»}}, // регистров и[4] [3]={{«es»}, {«cs»}, {«ss»}, {«ds»}}, // сегментных регистров[17]={«0123456789abcdef»},[20]; // таблица модификаторов

struct segt {

char name[8];len;

};segtab[2]; // таблица сегментовsymt {name[8];sgm;dsp;

};symtab[10]; // таблица метокstk2pol (char st[80], char pol[4] [8]); // разбиение строки на поляfindop (char op[8]); // поиск мнемокода в OPTABop2code (char nmb, char dis, char pol[4] [8], char code[4]);

// на входе мнемокод, на выходе длинна команды и объектный кодfindreg (char reg[8]); // поиск обознач. регистра в REGTABfindsegr (char reg[8]); // поиск обознач. сег. регистра в SEGRTAB

char findsym (char sym[8]); // поиск метки в SYMTAB

int str2num (char str[8]); // перевод строки в соотв. числоfindch (char c); // поиск поиск символа в HEXTAB

int step (int a, int b); // возведение A в степень B

int main()

{cod[4], lent, // код и длинна команды; // номер обработчика команды* ft; // исходный ассемблерный файлfn[]={«myprim.asm»};

ft=fopen (fn, «r+»);();

////////////////////////////first passage\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\(»*** first passage ***\n»);

seg=0;=0;=0;(! feof(ft)) // повторять пока не конец файла

{fgets (stk, 80, ft); // чтение строки(«\n»);();(stk);pol (stk, pole); // разбиение строки на поля

if (! strcmp (pole[1], «segment»)) //if второе поле SEGMENT

{seg++; // увеличение номера сегмента, запись=0; // названия в SEGTAB, сброс счетчика

strcpy (segtab [seg-1].name, pole[0]); // размещения;

}(! strcmp (pole[1], «ends»)) //if ENDS, то запись длинны сегм-та

{segtab [seg-1].len=cnt;(«add to segtab:%s % d % d\n»,[seg-1].name, seg, segtab [seg-1].len);;

}((! strcmp (pole[0], «assume»))||(! strcmp (pole[0], "\0»)))

continue; //if пустое поле-чтение сл. строки=findop (pole[0]);(num) //if код операции - увеличение

{lent=op2code (num, 0, pole, cod); // счет. размещ. на ее длинну

if (lent) {printf («lenght:%d\n», lent);+=lent;

}printf («Error: wrong operand!\n»);;

}((pole[0] [strlen (pole[0]) - 1]==':')||(! strcmp (pole[1], «dw»)))

{if (pole[0] [strlen (pole[0]) - 1]==':')[0] [strlen (pole[0]) - 1]='\0'; //if метка(findsym (pole[0])==-1) // не найдена в SYMTAB

{strcpy (symtab[psym].name, pole[0]); // занесение в SYMTAB[psym].sgm=seg;[psym].dsp=cnt;(«add to symtab:%s % d % d\n»,[psym].name, symtab[psym].sgm, symtab[psym].dsp);++;

} //if метка найдена - ошибкаprintf («Error: label % s retry!\n», pole[0]);(! strcmp(pole[1], "\0»)) continue;=findop (pole[1]);

if (num) //if код операции - увеличение

{lent=op2code (num, 1, pole, cod); // счет. размещ. на ее длинну

if (lent) {printf («lenght:%d\n», lent);+=lent;

}printf («Error: wrong operand!\n»);

}printf («Error: wrong mnemonic code!\n»);

} // во всех др. случаях - ошибка

}

////////////////////////////second passage\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* ftmp; // временные файлыfname[2] [10]={{«temp1.dat»}, {«temp2.dat»}};();();(»*** second passage ***\n»);=0;++;=0;(ft);

while (! feof(ft)) // повторять пока не конец файла

{fgets (stk, 80, ft); // чтение строки(«\n»);();(stk);pol (stk, pole); // разбиение строки на поля

if (! strcmp (pole[1], «segment»)) //if второе поле SEGMENT

{seg++; // увеличение номера сегмента=fopen (fname [seg-1], «w+b»); // открыть соотв. вр. файл=0; // сброс счетчика размещения;

}(! strcmp (pole[1], «ends»)) //if ENDS-заткрыть соотв. вр. файл

{fclose (ftmp);;

}((! strcmp (pole[0], «assume»))||(! strcmp (pole[0], "\0»)))

continue; //if пустое поле-чтение сл. строки=findop (pole[0]);(num) //if мнемокод операции - запись

{lent=op2code (num, 0, pole, cod); // объектн. кода во вр. файл

if (lent) {printf («code:»);(i=0; i<lent; i++)

{printf («%x», cod[i]);(cod[i], ftmp);

}+=lent;(«\n»);

}printf («Error: wrong operand!\n»);;

}=findop (pole[1]);(num) //if мнемокод операции - запись

{lent=op2code (num, 1, pole, cod); // объектн. кода во вр. файл(lent) {printf («code:»);(i=0; i<lent; i++)

{printf («%x», cod[i]);(cod[i], ftmp);

}+=lent;(«\n»);

}printf («Error: wrong operand!\n»);

} // во всех др. случаях - ошибка

}

/////////////////////creation object file\\\\\\\\\\\\\\\\\\\\\\\\\\* fobj; // создание объектн. файлаfnobj[]={«myprim.obj»};=fopen (fnobj, «w+b»);(fobj, «%c % c % c % c % s % c», 0x80,0xc, 0x0,0xa, «myprim.asm», 0x5d);

// название исходного ассемблерного файла(fobj, «%c % c % c % c % c % c % s % c», 0x88,0x20,0x0,0x0,0x0,0x1c,

«Turbo Assembler Version 3.2», 0x99); // версия ассемблера(fobj, «%c % c % c % c % c % c % c % c % c % c % s % c», 0x88,0x12,0x0,0x40,0xe9,

xb5,0x6e, 0xb0,0x30,0xa, «myprim.asm», 0x23);

// дополнительная запись с названием исходного ассемблерного файла

fprintf (fobj, «%c % c % c % c % c % c % c % c % c % c % c % c % c % c % c % c % c», 0x88,0x3,

x0,0x40,0xe9,0x4c, 0x96,0x2,0x0,0x0,0x68,0x88,0x3,0x0,0x40,

0xa1,0x94); // три постоянных записи(char y=0; y<=1; y++) // Две записи описания сегментов

{=0;=0x96; c+=i; putc (i, fobj);=strlen (segtab[y].name)+2; c+=i; putc (i, fobj);=0; c+=i; putc (i, fobj);=strlen (segtab[y].name); c+=i; putc (i, fobj);(char x=0; x<strlen (segtab[0].name); x++)

{i=toupper (segtab[y].name[x]); c+=i;(i, fobj);

}=0-c; putc (i, fobj);=0;=0x98; c+=i; putc (i, fobj);=0x7; c+=i; putc (i, fobj);=0x0; c+=i; putc (i, fobj);=0x60; c+=i; putc (i, fobj);=segtab[y].len; c+=i; putc (i, fobj);=0x0; c+=i; putc (i, fobj);=y+2; c+=i; putc (i, fobj);=0x1; c+=i; putc (i, fobj);=0x1; c+=i; putc (i, fobj);=0-c; putc (i, fobj);

}(fobj, «%c % c % c % c % c % c % c», 0x88,0x4,0x0,0x40,0xa2,0x1,0x91);

// запись начала сегментов (предсегментная запись)(y=0; y<=1; y++) // запись - тело сегментов

{=0;=0xa0; c+=i; putc (i, fobj);=segtab[y].len+4; c+=i; putc (i, fobj);=0; c+=i; putc (i, fobj);=y+1; c+=i; putc (i, fobj);=0; c+=i; putc (i, fobj);=0; c+=i; putc (i, fobj);=fopen (fname[y], «rb»);(char x=0; x<segtab[y].len; x++)

{i=getc(ftmp); c+=i;(i, fobj);

}(ftmp);=0-c; putc (i, fobj);

}[pmdf]='\0'; // запись - таблица ссылок(модификаторов)

c=0;=0x9c; c+=i; putc (i, fobj);=2*strlen(modif)+1; c+=i; putc (i, fobj);=0; c+=i; putc (i, fobj);=0xc8; c+=i; putc (i, fobj);=modif[0]; c+=i; putc (i, fobj);=0x54; c+=i; putc (i, fobj);=modif[1]; c+=i; putc (i, fobj);(y=2; y<strlen(modif); y+=2)

{i=0xc4; c+=i; putc (i, fobj);=modif[y]; c+=i; putc (i, fobj);=0x54; c+=i; putc (i, fobj);=modif [y+1]; c+=i; putc (i, fobj);

}=0-c; putc (i, fobj);(fobj, «%c % c % c % c % c % c % c % c % c % c», 0x8a, 0x7,0x0,

xc1,0x0,0x2,0x2,0x0,0x0,0xaa);

// запись - конец объектного файла

/////////////////////system information\\\\\\\\\\\\\\\\\\\\\\\\\\();();(» SYMTAB\n»); // вывод на экран таблиц:

printf (» name disp seg \n»); //SYMTAB, SEGTAB и табл. ссылок(i=0; i<psym; i++)(«%s %d %d \n»,[i].name, symtab[i].dsp, symtab[i].sgm);(«\n»);(» SEGTAB\n»);(» name N lent \n»);(i=0; i<2; i++)(«%s %d %d \n»,[i].name, i, segtab[i].len);(«\n»);

//printf («modifikatory \n»);

//for (i=0; i<pmdf; i++) printf («%x», modif[i]);(«\n»);(ft);(fobj);

getch();(0); // выход из транслятора.

}stk2pol (char st[80], char pol[4] [8]) // разбиение строки на поля

{fl=0, k=0, j=0; // внутр. перем.-счетчики и флаги=0;((st[i]!='\0')&&(st[i]!='\n')) // повторять пока не конец строки

{if((st[i]==' ')||(st[i]==', ')||(st[i]=='')||(j==8))

{if (fl) //if разделитель - переход на

{pol[k] [j]='\0'; // заполн. следующего поля

j=0;++;(k==4) return; //max кол-во полей = 4=0;

}

}if (st[i]==';') {for (; k<=3; k++) pol[k] [0]='\0';

return; //if комментарий - поля нулевые

}{fl=1; // запись символа в текущее поле

pol[k] [j]=st[i];++;

}++;

}[k] [j]='\0';++;(; k<=3; k++) pol[k] [0]='\0';; // конец stk2pol

}findop (char op[8]) // поиск мнемокода в OPTAB

{for (i=0; i<=7; i++) if (! strcmp (optab[i], op)) return (i+1);(0);}findsym (char sym[8]) // поиск метки в SYMTAB

{for (i=0; i<=psym; i++) if (! strcmp (symtab[i].name, sym)) return(i);(-1);

}findreg (char reg[8]) // поиск обознач. регистра в REGTAB

{for (i=0; i<=7; i++) if (! strcmp (regtab[i], reg)) return(i);(-1);

}findsegr (char reg[8]) // поиск обознач. сег. регистра в SEGRTAB

{for (i=0; i<=3; i++) if (! strcmp (segrtab[i], reg)) return(i);(-1);

}op2code (char nmb, char dis, char pol[4] [8], char code[4])

// ф-ция обработки команд ассемблера и директив

{struct bits // структура для доступа к

{char b0:1; char b1:1; char b2:1; char b3:1; // к отдельным битам.

char b4:1; char b5:1; char b6:1; char b7:1;

};bytes

{char c;b;

} temp, bcode;int2ch

{char c[2];d;

} tmp2;regn, regn2, segrn, tmp3; //regn, regn2, segrn-номера регистров

dis++;(nmb) // переход на обработчик соотв. команды

// MOV

{case 1: regn=findreg (pol[dis]);=findreg (pol[dis+1]);=findsegr (pol[dis]);

// непосредственная адресация((! regn)&&(! strcmp (segtab[0].name, pol [dis+1])))

{code[0]=0xb8; code[1]=0; code[2]=0; // код операции(npr) {modif[pmdf]=(cnt+3) - 2;++;[pmdf]=1;++;

}(3); // обраб. возвращ. длинну команды

}

// регистр в сегментный регистр((segrn!=-1)&&(regn2!=-1))

{code[0]=0x8e; // код операции.c=0xc0;.c=segrn;.b.b3=temp.b.b0; // номер сегментного регистра

bcode.b.b4=temp.b.b1;.c=regn2;.b.b0=temp.b.b0; // номер регистра.b.b1=temp.b.b1;.b.b2=temp.b.b2;[1]=bcode.c;

return(2); // обраб. возвращ. длинну команды

}((regn!=-1)||(regn2!=-1))

// Память в/из регистр AX (AL)

{if ((! regn)||(! regn2))

{bcode.c=0xa1; // код операции

if (regn) {bcode.b.b1=1; regn=regn2;}dis++;[0]=bcode.c;(npr)

{tmp3=findsym (pole[dis]);(tmp3==-1) return(0);{tmp2.d=symtab[tmp3].dsp;[1]=tmp2.c[0];[2]=tmp2.c[1];

}[pmdf]=(cnt+3) - 2;++;[pmdf]=symtab[tmp3].sgm;++;

}{code[1]=0; code[2]=0;}(3); // обраб. возвращ. длинну команды

}

// Регистр/память в/из регистр

{bcode.c=0x8b; // код операции

if (regn==-1) {bcode.b.b1=0; regn=regn2;}dis++;[0]=bcode.c;.c=0x06;.c=regn;

bcode.b.b3=temp.b.b0; // номер регистра -> код операции

bcode.b.b4=temp.b.b1;.b.b5=temp.b.b2;[1]=bcode.c;(npr)

{tmp3=findsym (pole[dis]);(tmp3==-1) return(0);{tmp2.d=symtab[tmp3].dsp;[2]=tmp2.c[0];[3]=tmp2.c[1];

}[pmdf]=(cnt+4) - 2;++;[pmdf]=symtab[tmp3].sgm;++;

}{code[2]=0; code[3]=0;}(4); // обраб. возвращ. длинну команды

}

};

//NEG2: regn=findreg (pol[dis]); (regn!=-1)

{code[0]=0xf7; // код операции

bcode.c=0xd8;.c=regn;

bcode.b.b0=temp.b.b0; // номер регистра -> код операции

bcode.b.b1=temp.b.b1;.b.b2=temp.b.b2;[1]=bcode.c;(2);

};

//JE3: if (npr)

{tmp3=findsym (pole[dis]);(tmp3==-1) return(0);code[1]=symtab[tmp3].dsp - (cnt+2); // определ. смешения

}code[1]=0;[0]=0x74; // код операции(2);;

//INC4: regn=findreg (pol[dis]);(regn!=-1)

{bcode.c=0x40; // код операции.c=regn;.b.b0=temp.b.b0; // номер регистра -> код операции.b.b1=temp.b.b1;.b.b2=temp.b.b2;[0]=bcode.c;

return(1); // обраб. возвращ. длинну команды

};

//SHL5: regn=findreg (pol[dis]);((regn!=-1)&&(! strcmp (pol[dis+1], «1»)))

{code[0]=0xd1; // код операции.c=0xe0;.c=regn;.b.b0=temp.b.b0; // номер регистра -> код операции.b.b1=temp.b.b1;.b.b2=temp.b.b2;[1]=bcode.c;

return(2); // обраб. возвращ. длинну команды

};

//ADC6: regn=findreg (pol[dis]);

if (regn!=-1)

{code[0]=0x13; // код операции

bcode.c=0xc0;.c=regn;

bcode.b.b3=temp.b.b0; // номер регистра -> код операции

bcode.b.b4=temp.b.b1;.b.b5=temp.b.b2;=findreg (pol[dis+1]);(regn!=-1)

{temp.c=regn;.b.b0=temp.b.b0; // номер регистра -> код операции.b.b1=temp.b.b1;.b.b2=temp.b.b2;[1]=bcode.c;

return(2); // обраб. возвращ. длинну команды

}

};

//INT7: code[0]=0xcd; // код операции[1]=str2num (pol[dis]);(code[1]!=-1) return(2);;

//DW8: tmp2.d=str2num (pol[dis]);[0]=tmp2.c[0];[1]=tmp2.c[1];(tmp2.d!=-1) return(2);;

}(0); //if ошибка - длинна ноль

}str2num (char str[8]) // перевод строки в соотв. число

{int zn, j;=0;=0;(str [strlen(str) - 1]=='h') // шестнадцатеричное число

for (char k=strlen(str) - 2; k>=0; k-)

{if (findch (str[k])==-1) return(-1); // не правильный формат - ошибка

zn=zn+(findch (str[k]))*step (16, j);++;

}// десятичное число

{for (char k=strlen(str) - 1; k>=0; k-)

{if (findch (str[k])==-1) return(-1);=zn+(findch (str[k]))*step (10, j);++;

}

}(zn);

}findch (char c) // поиск символа в HEXTAB

{for (i=0; i<=15; i++) if (hextab[i]==c) return(i);(-1);

}

step (int a, int b) // возведение A в степень B

{int z=1;(i=0; i<b; i++) z=z*a; return(z).


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


1.Абель П. Ассемблер и программирование для IBM PC. Технологический институт Британская Колумбия.

2.Журден Р. Справочник программиста на персональном компьютере фирмы IBM.

.Зубков С.В. Assembler для DOS, Windows и Unix. - М.: ДМК Пресс, 2000. - 608 с.: ил. (Серия для программистов).



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

Больше работ по теме:

КОНТАКТНЫЙ EMAIL: [email protected]

Скачать реферат © 2017 | Пользовательское соглашение

Скачать      Реферат

ПРОФЕССИОНАЛЬНАЯ ПОМОЩЬ СТУДЕНТАМ