IPB
ЛогинПароль:

> ПРАВИЛА РАЗДЕЛА!!!

1. Заголовок или название темы должно быть информативным
2. Все тексты программ должны помещаться в теги [CODE=asm] [/CODE]
3. Прежде чем задавать вопрос, см. "FAQ",если там не нашли ответа, воспользуйтесь ПОИСКОМ, возможно, такую задачу уже решали!
4. Не предлагайте свои решения на других языках, кроме Ассемблера. Исключение только с согласия модератора.
5. НЕ используйте форум для личного общения! Все, что не относиться к обсуждению темы - на PM!
6. Проверяйте программы перед тем, как выложить их на форум!!

 
 Ответить  Открыть новую тему 
> ассемблерная вставка в Delphi, макросы
сообщение
Сообщение #1


Бывалый
***

Группа: Пользователи
Сообщений: 198
Пол: Мужской

Репутация: -  1  +


доброго дня
необходимо вычислить интеграл методом прямоугольников (ассемблерная вставка в 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
...

[Error] Project1.dpr(18): Undeclared identifier: 'funct'
думал что макросы описываются след образом:
<имя> macro парам1, парам2... парам N
...
...набор команд
...
endm
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #2


Гуру
*****

Группа: Пользователи
Сообщений: 1 013
Пол: Мужской
Ада: Разработчик
Embarcadero Delphi: Сторонник
Free Pascal: Разработчик

Репутация: -  627  +


MACRO встроенным ассемблером не поддерживается. Поддерживаются инструкции, а не препроцессор. Используй функции.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #3


Бывалый
***

Группа: Пользователи
Сообщений: 198
Пол: Мужской

Репутация: -  1  +


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.

почему происходит деление на ноль? я же прибавляю перед делением h
fld x 
fadd h
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #4


Бывалый
***

Группа: Пользователи
Сообщений: 198
Пол: Мужской

Репутация: -  1  +


аа, дело в
fdivr st(1),st

кажется там на каждом шаге номер меняется?
на первом шаге надо st(5) делить на st(6)? или я неправильно понял структуру стека?

Сообщение отредактировано: marwell -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #5


Гуру
*****

Группа: Пользователи
Сообщений: 1 013
Пол: Мужской
Ада: Разработчик
Embarcadero Delphi: Сторонник
Free Pascal: Разработчик

Репутация: -  627  +


А кто тебе сказал, что происходит деление на 0? smile.gif

Посмотри внимательно на скриншот, и скажи, что будет, когда я нажму на F7 для выполнения следующего шага (операции fdivr), и почему?
Прикрепленное изображение

Вот ответ: (Показать/Скрыть)
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #6


Бывалый
***

Группа: Пользователи
Сообщений: 198
Пол: Мужской

Репутация: -  1  +


сорри, успел отредактировать свое предыдущее сообщение до того как увидел ваш ответ
а насчет прикрепленной картинки, как то не очень понятно wacko.gif

Добавлено через 6 мин.
на каком то шаге тангенс равен 0?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #7


Гуру
*****

Группа: Пользователи
Сообщений: 1 013
Пол: Мужской
Ада: Разработчик
Embarcadero Delphi: Сторонник
Free Pascal: Разработчик

Репутация: -  627  +


Посмотри на содержимое стека FPU. Сколько там осталось свободных регистров? Нисколько. Вот поэтому и вылет: переполнение стека FPU. Чистить стек нужно.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #8


Бывалый
***

Группа: Пользователи
Сообщений: 198
Пол: Мужской

Репутация: -  1  +


спасибо!
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.

осталось понять почему считает неправильно. res почему то всегда равен введенному n
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #9


Гуру
*****

Группа: Пользователи
Сообщений: 1 013
Пол: Мужской
Ада: Разработчик
Embarcadero Delphi: Сторонник
Free Pascal: Разработчик

Репутация: -  627  +


Функция какая у тебя, тангенс или котенгенс? Если тангенс - то вот так:

   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);

(логика очень проста: в стеке держим только приращение в ST1, и текущее значение X в ST0, все остальное сразу после вычисления убираем). Если функция - КОтангенс - поменяй fdivp на fdivrp
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #10


Бывалый
***

Группа: Пользователи
Сообщений: 198
Пол: Мужской

Репутация: -  1  +


Цитата(IUnknown @ 24.05.2012 15:27) *

Функция какая у тебя, тангенс или котенгенс? Если тангенс - то вот так:

   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);

(логика очень проста: в стеке держим только приращение в ST1, и текущее значение X в ST0, все остальное сразу после вычисления убираем). Если функция - КОтангенс - поменяй fdivp на fdivrp

спасибо! да, тангенс нужен. И логика понятна.
Только Delphi ругается на эту строчку
fadd st(1)

говорит [Error] Project1.dpr(25): Invalid combination of opcode and operands
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #11


Гуру
*****

Группа: Пользователи
Сообщений: 1 013
Пол: Мужской
Ада: Разработчик
Embarcadero Delphi: Сторонник
Free Pascal: Разработчик

Репутация: -  627  +


FPC не ругается, в Дельфи сейчас посмотрю.

Update
Да, замени ту строку вот на эту:
      fadd st, st(1)


Сообщение отредактировано: IUnknown -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #12


Бывалый
***

Группа: Пользователи
Сообщений: 198
Пол: Мужской

Репутация: -  1  +


Цитата(IUnknown @ 24.05.2012 16:29) *

FPC не ругается, в Дельфи сейчас посмотрю.

Update
Да, замени ту строку вот на эту:
      fadd st, st(1)


сделал. Запускается без ошибок. Вот только ответ... Ответ должен быть приблизительно 0.261168 да? А прога при n=100 выдает 62,3434. Чем больше n, тем дальше ответ растет wacko.gif
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #13


Гуру
*****

Группа: Пользователи
Сообщений: 1 013
Пол: Мужской
Ада: Разработчик
Embarcadero Delphi: Сторонник
Free Pascal: Разработчик

Репутация: -  627  +


Не верю smile.gif Ты просто не доделал метод прямоугольников. Вот код, вычисляющий значение и на Ассемблере, и на Паскале:

program Project1;

{$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.
Чем выше N - тем выше точность. А так значения абсолютно одинаковые.

Сообщение отредактировано: IUnknown -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #14


Бывалый
***

Группа: Пользователи
Сообщений: 198
Пол: Мужской

Репутация: -  1  +


Цитата(IUnknown @ 24.05.2012 17:41) *

Не верю smile.gif Ты просто не доделал метод прямоугольников. Вот код, вычисляющий значение и на Ассемблере, и на Паскале:

program Project1;

{$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.
Чем выше N - тем выше точность. А так значения абсолютно одинаковые.

большое и уже не первое спасибо smile.gif
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 

 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 



- Текстовая версия 8.04.2025 16:13
500Gb HDD, 6Gb RAM, 2 Cores, 7 EUR в месяц — такие хостинги правда бывают
Связь с администрацией: bu_gen в домене octagram.name