| Арк.
18
Зм. | Арк. | № докум | Підпис | Дата
var[e]=0;
v=0;
for(e=0;in[i]!=0x0A;i++,e++) // Читання ідентифікатора
{
if(!isalpha(in[i])) // Якщо далі йде вираз, а не змінна
{
v=0;
break;
}
v=1;
op1[e]=in[i]; // Читання ідентифікатора
}
if(v) // Якщо є присвоєння значення змінної
{
op1[e]=0;
fprintf(fout,"\tmov ax,%s \n\tmov word[si+%s],ax \n",op1,var);
continue; // Запис конструкції в файл
}
else // Трансляція арифметичного виразу
{
for(l=0;in[i]!=0x0A;i++,l++)
ex[l]=in[i]; // Читання виразу
ex[l]=0;
while(1) // Обробка виразу
{
if(ex[0]=='@'&&ex[1]==0) // Якщо трансльований увесь вираз
break;
for(e=v=current=0;e<l;pr[e++]=current) // Визначення пріоритету
{
if(ex[e]==')'||ex[e]=='+'||ex[e]=='-'||ex[e]=='*'||ex[e]=='/')
КП.КС-05.00.00.000 ПЗ | Арк.
19
Зм. | Арк. | № докум | Підпис | Дата
{
current--; // Якщо це дужка, що закривається або
number=0; // символ операції, пріоритет
v=0; // зменшується на одиницю
}
if(ex[e]=='('||ex[e]=='@')
{
current++; // Якщо це дужка, що відкривається або
number=0; // тимчасова змінна, пріоритет
v=0; // збільшується на одиницю
}
if(isdigit(ex[e])&&!number)
{
number=1; // Якщо це число, пріоритет
current++; // збільшується на одиницю
}
if(isalpha(ex[e])&&!v)
{
v=1; // Якщо це ідентифікатор, пріоритет
current++; // збільшується на одиницю
}
}
for(max=e=0;e<l;e++) // Визначення максимального пріоритету
if(pr[e]>max)
max=pr[e];
for(e=0;e<l;e++) // Визначення індексу елементу з
if(pr[e]==max) // максимальним пріоритетом
break;
for(k=L1=0;isdigit(ex[e])&&isalpha(ex[e]&&ex[e]=='@');L1++,e++,k++)
op1[k]=ex[e]; // Читання першого операнду
КП.КС-05.00.00.000 ПЗ | Арк.
20
Зм. | Арк. | № докум | Підпис | Дата
op1[k]=0;
oper=ex[e]; // Читання символу операції
for(k=L2=0;isdigit(ex[e])&&isalpha(ex[e]&&ex[e]=='@');L2++,e++,k++)
op2[k]=ex[e]; // Читання другого операнду
op2[k]=0;
for(k=0,imm1=1;k<L1;k++) // Визначення, перший операнд є числом
if(!isdigit(op1[k])) // чи ідентифікатором
{
imm1=0;
break;
}
for(k=0,imm2=1;k<L2;k++) // Визначення, другий операнд є числом
if(!isdigit(op2[k])) // чи ідентифікатором
{
imm2=0;
break;
}
switch(oper) // Вибір відповідної конструкції
{
case '+': // Додавання
if(op1[0]=='@')
if(imm2)
fprintf(fout,"\tadd ax,%s \n",op2); // @+imm2
else
fprintf(fout,"\tadd ax,[si+%s] \n",op2); // @+var2
else
if(op2[0]=='@')
if(imm1)
fprintf(fout,"\tadd ax,%s \n",op1); // imm1+@
else
КП.КС-05.00.00.000 ПЗ | Арк.
21
Зм. | Арк. | № докум | Підпис | Дата
fprintf(fout,"\tadd ax,[si+%s] \n",op1); // var1+@
else
if(imm2)
fprintf(fout,"\tmov ax,%s \n\tadd ax,%s \n",op1,op2);// imm1|var1+imm2
else
fprintf(fout,"\tmov ax,%s \n\tadd ax,[si+%s] \n",op1,op2); // imm1|var1+var2
case '-': // Віднімання
if(op1[0]=='@')
if(imm2)
fprintf(fout,"\tsub ax,%s \n",op2); // @-imm2
else
fprintf(fout,"\tsub ax,[si+%s] \n",op2); // @-var2
else
if(op2[0]=='@')
if(imm1)
fprintf(fout,"\tsub ax,%s \n\tneg ax \n",op1); // imm1-@
else
fprintf(fout,"\tsub ax,[si+%s] \n\tneg ax \n",op1); // var1-@
else
if(imm2)
fprintf(fout,"\tmov ax,%s \n\tsub ax,%s \n",op1,op2);// imm1|var1-imm2
else
fprintf(fout,"\tmov ax,%s \n\tsub ax,[si+%s] \n",op1,op2); // imm1|var1-var2
case '*': // Множення
if(op1[0]=='@')
if(imm2)
fprintf(fout,"\timul ax,%s \n",op2); // @*imm2
else
fprintf(fout,"\timul word ptr[si+%s] \n",op2); // @*var2
else
КП.КС-05.00.00.000 ПЗ | Арк.
22
Зм. | Арк. | № докум | Підпис | Дата
if(op2[0]=='@')
if(imm1)
fprintf(fout,"\timul ax,%s \n",op1); // imm1*@
else
fprintf(fout,"\timul word ptr[si+%s] \n",op1); // var1*@
else
if(imm1)
fprintf(fout,"\timul ax,[si+%s],%s \n",op2,op1); // imm1*var2
else
if(imm2)
fprintf(fout,"\timul ax,[si+%s],%s \n",op1,op2); // var1*imm2
else // imm1|var1*var2
fprintf(fout,"\tmov ax,%s \n\timul ax,[si+%s] \n",op1,op2);
case '/': // Ділення
{
fprintf(fout,"\txor dx,dx \n");
if(op1[0]=='@')
if(imm2)
fprintf(fout,"\tmov bx,%s \n\tidiv bx \n",op2); // @/imm2
else
fprintf(fout,"\tidiv word ptr[si+%s] \n",op2); // @/var2
else
if(op2[0]=='@')
if(imm1)
fprintf(fout,"\tmov bx,%s \n\txchg ax,bx \n\tidiv bx \n",op1);// imm1/@
else
fprintf(fout,"\tmov bx,[si+%s] \n\txchg ax,bx \n\tidiv bx \n",op1);// var1/@
else
if(imm1) // imm1/var2
fprintf(fout,"\tmov bx,%s \n\tidiv word ptr[si+%s] \n",op1,op2);
КП.КС-05.00.00.000 ПЗ | Арк.
23
Зм. | Арк. | № докум | Підпис | Дата
else
if(imm2) // imm1|var1/imm2
fprintf(fout,"\tmov ax,%s \n\tmov bx,%s \n\tidiv bx \n",op1,op2);
else // imm1|var1/var2
fprintf(fout,"\tmov ax,%s \n\tidiv word ptr[si+%s] \n",op1,op2);
}
}
shift=e-L1-L2-2; // Обчислення величини зсуву
shift*=(shift>=0);
ex[shift]='@'; // Заміна триплету на @
shift++;
for(e=shift;e<l;e++)
ex[e]=ex[e+shift+2]; // Зсув виразу
l-=shift+2; // Зменшення довжини виразу
}
fprintf(fout,"\tmov %s,ax \n",var); // Запис присвоєння значення виразу
}
}
fclose(fin); // Закриття вхідного файлу
// Закінчення основної програми
fprintf(fout,"\tmov ah,1\n\tint 21h\n\tmov ah,4Ch\n\tint 21h\n\n");
if((fin=fopen("input_r.txt","r"))==NULL)// Відкриття файлу з підпрограмою
{ // вводу змінної з клавіатури
printf("Cannot open input_r.txt"); // Повідомлення про помилку
return 0; // Вихід з програми
}
while(!feof(fin))
fputc(fgetc(fin),fout); // Копіювання підпрограми в файл
fclose(fin); // Закриття файлу input_r.txt
fseek(fout,-1,1);
КП.КС-05.00.00.000 ПЗ | Арк.
24
Зм. | Арк. | № докум | Підпис | Дата
if((fin=fopen("print_r.txt","r"))==NULL) // Відкриття файлу з підпрограмою
{ // виводу змінної на екран
printf("Cannot open print_r.txt"); // Повідомлення про помилку
return 0; // Вихід з програми
}
while(!feof(fin))
fputc(fgetc(fin),fout); // Копіювання підпрограми в файл
fclose(fin); // Закриття файлу print_r.txt
fseek(fout,-1,1);
fprintf(fout,"code ends\nend main"); // Кінець модуля
fclose(fout); // Закриття вихідного файлу
system("tasm.exe /r res.asm"); // Виклик tasm.exe
system("tlink.exe /3 res.obj"); // Виклик tlink.exe
}
КП.КС-05.00.00.000 ПЗ | Арк.
25
Зм. | Арк. | № докум | Підпис | Дата
5 ТЕКСТ ПІДПРОГРАМ
; Підпрограма вводу 16-розрядної знакової змінної з клавіатури з
; використанням функції 01h операційної системи MSDOS. Параметром
; підпрограми є зміщення змінної в ВХ. Введення числа припиняється після
; вводу 5 цифр (+ знак ‘–‘ ) або натиснення клавіші Enter.
input: mov byte ptr conv+9,0 ; Попередньо вважаємо число додатнім
xor edx,edx ; EDX=0
mov cx,5 ; Число цифр, що можна ввести
mov ah,1 ; Функція вводу символу
int 21h ; з клавіатури
cmp al,'-' ; Від'ємний знак?
jnz plus_i ; Ні, додатній (в AL перша цифра числа)
mov byte ptr conv+9,80h ; Запис знаку
d_in: int 21h ; Ввід символу
plus_i: cmp al,0Dh ; Це Enter?
jz end_i ; Так, кінець вводу числа
shl edx,4 ; Зсув числа для вставки тетради
and al,0Fh ; Очищення зайвих біт
or dl,al ; Вставка тетради
loop d_in ; Повтор циклу 5 разів
end_i: mov dword ptr conv,edx ; Запис числа
finit ; Очищення стеку 80387
fbld tbyte ptr conv ; Читання числа в 80387
fist word ptr [bx] ; Збереження числа за адресою змінної
ret ; Вихід з підпрограми
; Підпрограма виводу 16-розрядної знакової змінної на екран з використанням
; функції 02h операційної системи MSDOS. Передуючі нулі числа не виводяться.
; Параметром підпрограми є зміщення змінної в ВХ.
print: finit ; Очищення стеку 80387
КП.КС-05.00.00.000 ПЗ | Арк.
26
Зм. | Лист | № докум | Підпис | Дата
fild word ptr [bx] ; Читання змінної в 80387
fbstp tbyte ptr conv ; Запис двійково-десяткового числа
mov ah,2 ; Функція