доброго дня
необходимо вычислить интеграл методом прямоугольников (ассемблерная вставка в Delphi или в паскаль)
сам метод мне понятен
но, на каждом шаге мне нужно будет вычислять значение функции в определенной точке. хотел было использовать макросы
но не тут то было, ни паскаль ни Delphi макросы не принимают
может я неправильно описываю эти макросы?
var n,a,b: integer;
res, h, x: real;
begin
readln(n);
a:=0;
b:=1;
asm
fild b
fisub a
fidiv n
call funct
funct proc
...
MACRO встроенным ассемблером не поддерживается. Поддерживаются инструкции, а не препроцессор. Используй функции.
var n,a,b: integer;
res, h, x: real;
begin
readln(n);// ввод количества частичных отрезков
a:=0; // a и b - границы
b:=1;
x:=0; // частичная сумма
res:=0;
asm
fild b // загрузка b на вершину стека
fisub a // b-a
fidiv n // :n
fst h // значение из вершины в h
mov ecx,n
@m: fld x
fadd h
fst x
fptan
fdivr st(1),st
fadd res
fst res
loop @m;
end;
writeln(res:5:4);
readln;
end.
fld x
fadd h
аа, дело в
fdivr st(1),st
А кто тебе сказал, что происходит деление на 0?
Посмотри внимательно на скриншот, и скажи, что будет, когда я нажму на F7 для выполнения следующего шага (операции fdivr), и почему?
сорри, успел отредактировать свое предыдущее сообщение до того как увидел ваш ответ
а насчет прикрепленной картинки, как то не очень понятно
Добавлено через 6 мин.
на каком то шаге тангенс равен 0?
Посмотри на содержимое стека FPU. Сколько там осталось свободных регистров? Нисколько. Вот поэтому и вылет: переполнение стека FPU. Чистить стек нужно.
спасибо!
var n,a,b: integer;
res, h, x: real;
begin
readln(n);// ââîä êîëè÷åñòâà ÷àñòè÷íûõ îòðåçêîâ
a:=0; // a è b - ãðàíèöû
b:=1;
x:=0; // ÷àñòè÷íàÿ ñóììà
res:=0;
asm
fild b // çàãðóçêà b íà âåðøèíó ñòåêà
fisub a // b-a
fidiv n // :n
fstp h // çíà÷åíèå èç âåðøèíû â h
mov ecx,n
@m: fld x
fadd h
fst x
fptan
fdivr st(1),st
fadd res
fstp res
finit
loop @m;
end;
writeln(res:5:4);
readln;
end.
Функция какая у тебя, тангенс или котенгенс? Если тангенс - то вот так:
asm
fild b
fisub a
fidiv n
fst h
mov ecx, n
fld x
@m:
fadd st(1)
fld st(0) // Дублируем значение Х
fptan
fdivp st(1),st
fadd res
fstp res
loop @m;
end;
writeln(res:5:4);
asm
fild b
fisub a
fidiv n
fst h
mov ecx, n
fld x
@m:
fadd st(1)
fld st(0) // Дублируем значение Х
fptan
fdivp st(1),st
fadd res
fstp res
loop @m;
end;
writeln(res:5:4);
fadd st(1)
FPC не ругается, в Дельфи сейчас посмотрю.
Update
Да, замени ту строку вот на эту:
fadd st, st(1)
fadd st, st(1)
Не верю Ты просто не доделал метод прямоугольников. Вот код, вычисляющий значение и на Ассемблере, и на Паскале:
program Project1;Чем выше N - тем выше точность. А так значения абсолютно одинаковые.
{$APPTYPE CONSOLE}
uses math;
var n, a, b: integer;
res, h, x: real;
i : Integer;
begin
// readln(n);
n := 15000;
a := 0;
b := 1;
x := 0;
res := 0;
asm
fild b
fisub a
fidiv n
fst h
mov ecx, n
fld x
@m:
fadd st, st(1)
fld st(0)
fptan
fdivp st(1), st
fadd res
fstp res
loop @m;
fld res
fmul st, st(2)
fstp res
end;
writeln(res:5:4);
// Test
h := (b - a) / n;
x := 0;
res := 0;
for i := 1 to n do
begin
x := x + h;
res := res + tan(x);
end;
res := res * h;
writeln(res:5:4);
readln;
end.
program Project1;Чем выше N - тем выше точность. А так значения абсолютно одинаковые.
{$APPTYPE CONSOLE}
uses math;
var n, a, b: integer;
res, h, x: real;
i : Integer;
begin
// readln(n);
n := 15000;
a := 0;
b := 1;
x := 0;
res := 0;
asm
fild b
fisub a
fidiv n
fst h
mov ecx, n
fld x
@m:
fadd st, st(1)
fld st(0)
fptan
fdivp st(1), st
fadd res
fstp res
loop @m;
fld res
fmul st, st(2)
fstp res
end;
writeln(res:5:4);
// Test
h := (b - a) / n;
x := 0;
res := 0;
for i := 1 to n do
begin
x := x + h;
res := res + tan(x);
end;
res := res * h;
writeln(res:5:4);
readln;
end.
И всётаки, как в Delphi, с помощью asm можно вызвать прерывание, например int 31h ? Очень надо