Разработка калькулятора на основе рекурсивного спуска
1)Цель работы: Добавить в программу, модифицированную в предыдущей лабораторной работе, возможность вычисления простого арифметического выражения: реализовать сложение, вычитание, умножение и целочисленное деление.
Изменим процедуры обработки арифметического выражения следующим образом:
procedure ff(var resff:integer);
begin
scan(T,n);
if (T='i') then
begin
if not ((ub-length(sl))=1) then bofl:=false;
scan1(T,n);
if ((T='r')and(n=8)) then oppr(mid);
end
else if (T='c') then
begin
resff:=num;
end
else if (T='k') then
begin
if (n=4) then {opw};
end
else if (T='l') then
begin
end
else if ((T='r')and(n=5)) then
begin
ee(resff);
scan(T,n);
if ((T='r')and(n=6)) then begin end
else err(0);
end
else err(2);
end;
procedure tt(var restt:integer);
var rt:integer;
begin
ff(rt);
scan1(T,n);
while (not((T='r') and ((n=1) or (n=2) or (n=6) or (n=7)))) do
begin
scan(T,n);
if ((T='r') and (n=3)) then
begin
ff(mid);
restt:=rt*mid;
end
else
if ((T='r') and (n=4)) then
begin
ff(mid);
restt:=rt div mid;
end
else
|
|
err(1);
scan1(T,n);
end; end;
procedure ee(var resee:integer);
var re:integer;
begin
tt(re);
While (not(((T='r') and (n=7))or((T='r') and (n=6)))) do
begin
scan(T,n);
if ((T='r') and (n=1)) then
begin
tt(mid);
resee:=re+mid;
end
else
if ((T='r') and (n=2)) then
begin
tt(mid);
resee:=re-mid;
end
else
err(1);
scan1(T,n);
end; end;
Содержимое файла: 19+(32/8)-(45*3)#
В результате сканирования исходного текста получим сообщение:
Строка правильная
158
Результат оказался верным, следовательно арифметический анализатор работает верно.
Лабораторная работа №11
Генерация кода на ассемблере для арифметического выражения
1)Цель работы: Модифицировать «программу-калькулятор», созданную в прошлой лабораторной работе так, чтобы вместо в качестве семантических действий было не прямое вычисление результата, а генерация кода на ассемблере, с помощью которого после компиляции и компоновки новой программы, можно будет получить результат.
|
|
Изменим процедуры обработки арифметического выражения следующим образом:
procedure tt;
begin
ff;
scan1(t,n);
while not(((t='r')and((n=7)or(n=10)or(n=11)or(n=17)or(n=9)or(n=14)or(n=15)or(n=5)or(n=3)))or((t='R')and((n=4)or(n=5)or(n=6)))) do
begin
scan(t,n);
if (t='r') then
case n of
12: begin
ff;
writeln(final,'pop bx');
writeln(final,'pop ax');
writeln(final,'mul bx');
writeln(final,'push ax');
end;
13: begin
ff;
writeln(final,'pop bx');
writeln(final,'pop ax');
writeln(final,'div bx');
writeln(final,'push ax');
end;
else begin
err('ожидалось арифметическое действие');
end;
end
else err(' ожидалось арифметическое действие ');
scan1(t,n);
end;
end;
procedure ee;
begin
tt;
scan1(t,n);
while not(((t='r')and((n=7)or(n=17)or(n=9)or(n=14)or(n=15)or(n=5)or(n=3)))or((t='R')and((n=4)or(n=5)or(n=6)))) do
begin
scan(t,n);
if (t='r') then
case n of
10: begin
tt;
writeln(final,'pop bx');
writeln(final,'pop ax');
writeln(final,'add ax,bx');
writeln(final,'push ax');
end;
11: begin
tt;
writeln(final,'pop bx');
writeln(final,'pop ax');
writeln(final,'sub ax,bx');
writeln(final,'push ax');
end;
else begin
err(ожидалось арифметическое действие ');
end;
end
else err(ожидалось арифметическое действие ');
scan1(t,n);
end;
end;
procedure ff;
var temps:string;
k:integer;
begin
scan(t,n);
case t of
'c': begin
writeln(final,'mov ax,',sl);
writeln(final,'push ax');
end;
'i': begin
writeln(final,'mov ax,',sl);
|
|
writeln(final,'push ax');
end;
'r': begin
if (n=6) then
begin
ee;
scan(t,n);
if not ((t='r')and(n=7)) then err('ожидалась закрывающая скобка');
end
else err('ожидалась открывающая скобка')
end
else err('неожиданный символ');
end;
end;
Также изменим главный метод программы:
begin
prepare;
writeln(final,'.model tiny');
writeln(final,'.code');
writeln(final,'.386');
writeln(final,'org 100h');
writeln(final,'start:');
ee;
writeln(final,'pop ax');
writeln(final,'mov bx,10');
writeln(final,'mov di,0');
writeln(final,'mov si,ax');
writeln(final,'cmp ax,0');
writeln(final,'jns @a');
writeln(final,'neg si');
writeln(final,'mov ah,2');
writeln(final,'mov dl, "-"');
writeln(final,'int 21h');
writeln(final,'mov ax,si');
writeln(final,’@a:');
writeln(final,'mov dx,0');
writeln(final,'div bx');
writeln(final,'add dl, 30h');
writeln(final,'mov vivod [di],dl');
writeln(final,'inc di');
writeln(final,'cmp al,0');
writeln(final,'jnz @a');
writeln(final,'mov cx,di');
writeln(final,'dec di');
writeln(final,'mov ah,2');
writeln(final,'@b:');
writeln(final,'mov dl,vivod[di]');
writeln(final,'dec di');
writeln(final,'int 21h');
writeln(final,'loop @b');
writeln(final,'mov dl, " "');
writeln(final,'int 21h');
writeln(final,'ret');
writeln(final,'end start');
if (buf[ub]='(') then count:=count+1 else if (buf[ub]=')') then count:=count-1;
if (count<>0) then err(0);
writeln(' Строка правильная');
close(f);
assign(f,'D:\tab_i.txt');
append(f);
for i:=1 to z-1 do
writeln(f,tab_i[i]);
close(f);
end;
Содержание исходного файла: 19+(32/8)-(45*3)#
В результате сканирования исходного текста получим текстовый файл:
|
|
.model tiny
.code
.386
org 100h
start:
mov ax,19
push ax
mov ax,32
push ax
mov ax,8
push ax
pop bx
pop ax
div bx
push ax
pop bx
pop ax
add ax,bx
push ax
mov ax,45
push ax
mov ax,3
push ax
pop bx
pop ax
mul bx
push ax
pop bx
pop ax
sub ax,bx
push ax
pop ax
mov bx,10
mov di,0
mov si,ax
cmp ax,0
jns @met7
neg si
mov ah,2
mov dl, "-"
int 21h
mov ax,si
@met7:
mov dx,0
div bx
add dl, 30h
mov vivod [di],dl
inc di
cmp al,0
jnz @met7
mov cx,di
dec di
mov ah,2
@met8:
mov dl,vivod[di]
dec di
int 21h
loop @met8
mov dl, " "
int 21h
ret
end start
Скомпонуем и скомпилируем получившуюся программу на ассемблере. В результате запуска созданного нами .com-приложения получим сообщение:
158
Данный результат является верным, следовательно обе программы составлены и работают правильно.
Дата добавления: 2018-04-05; просмотров: 355; Мы поможем в написании вашей работы! |
Мы поможем в написании ваших работ!