#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 с.: ил. (Серия для программистов).