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

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

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

> Ошибка в программе вычисления интеграла, метод трапеций
Hey
сообщение 7.09.2012 20:32
Сообщение #1


Новичок
*

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

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


Приветствую,

пишу программу вычисления интеграла функции 1/ln x методом трапеций, для начала взял n=20 (затем буду увеличивать). Файл .exe создан, но выдает ошибку и вылетает. При просмотре в дебаггере вижу, что еще на этапе вычисления шага в регистре ST0 оказывается отрицательная величина, еще через пару шагов вылетает. В чем тут дело?

Заранее спасибо.


.486p
.model small 
.stack 100h
.data 
a dw 2
b dw 5
x dq 2
n dw 20
h dq ?
y dq ?

.code 
main proc
mov ax, @data
mov ds, ax
finit
fild b
fisub a
fidiv n
fst h  ;вычисляем шаг h 


fld1
fild b
fyl2x
fldln2
fmul
fld1
fdiv
fADD y
fild b
fdivr st(1), st ;вычисляем (ln a + ln b)/2

cycl:
fadd y
fst y 

fild x 
fadd h
fst x ;производим приращение х и каждый раз сохраняем
ficom b
je mult_  ;пока не равно b(=5),продолжаем 

fld x
fyl2x
fldln2
fmul
fld1 
fdiv ;
loop cycl ;

mult_: 
fld y ;
fld h ; 
fmul   ;когда х достиг значения 5, перемножаем на h

exit:   
mov ax, 4c00h ;
int 21h ;
main endp
end main

 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
 
 Ответить  Открыть новую тему 
Ответов
IUnknown
сообщение 15.09.2012 11:30
Сообщение #2


a.k.a. volvo877
*****

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

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


Hey, я опять не понял, зачем тебе 2 цикла, в каждом из которых ты вычисляешь значения интегралов? Давай запишем алгоритм который тебе нужен, в псевдокоде. Итак, чтобы определить, при каком N значение интеграла найдено с точностью Eps, тебе достаточно:

   n <- 0
y <- 0.0;
repeat
prev <- y;
n <- n + DeltaN;
y <- Integral(a, b, n);
until abs(y - z) < eps;
print "finally Int = ", y, " when n = ", n


Всё, никаких двойных циклов, все прекрасно делается одним. А теперь смотри, как это записывается на ассемблере (я заменил переменную z на prev):

main proc
	mov ax, @data
	mov ds, ax
	
outer_:
	fld y
	fstp prev
	; fldz
	; fstp y

	; вычисляем шаг для текущего N
	Сalc_h
	
	iCalcF b	; 1 / ln b
	fstp y
	iCalcF a	; 1 / ln a
	fadd y	; Складываем
	fdiv x	; Делим сумму на 2
	fstp y	; Сохр. начальное приближение
	
	; внутренний цикл - вычисляем интеграл
	fld x		; X в стек сопроцессора
inner_loop:
	fadd h	; X <- X + h
	CalcF	; F(X)
	fadd y
	fstp y	; Сохраняем измененное значение интеграла
	loop inner_loop
	
	fld y
	fmul h	; нашли окончательное значение при текущем N
	fst y		; сохранили его назад в Y для последующего сравнения с prev
	
	; дублируем значение с вершины стека
	; fld st
	
	; выводим значение интеграла и N
	call outfloat
	call OutInt ; выводим актуальное n
	
	fld y
	fsub prev
	fabs
	fcomp eps
	fstsw ax
	sahf
	jp uncomp
	jz m1
	jc exit
m1:
	jmp outer_
uncomp:
	mov dx, offset mes
	mov ah, 09
	int 21h

exit:
	mov ax, 4c00h ;
	int 21h ;
main endp
Проще, правда, чем делать дважды одно и то же?

Теперь насчет
Цитата
Вывод n также не работает.
Процедуру OutInt проверять не пробовал? smile.gif

Вообще-то, она должна выглядеть так (вообще-то, жестко задавать в программе, что процедура выводит именно N - это бред, лучше перед ее вызовом занести ax <- N):

outint  proc    near
        push    cx
        push    dx
        push    bx
        push    ax
	
	mov ax, n  ; <--- !!! А этого лучше не делать !!!

; Проверяем число на знак.
        test    ax, ax
        jns     short @oi1
; Если оно отрицательное, выведем минус и оставим его модуль.
        mov     ah, 02h
        mov     dl, '-'
        int     21h
        pop     ax
        push    ax
        neg     ax
; Количество цифр будем держать в CX.
@oi1:   xor     cx, cx
        mov     bx, 10
@oi2:   xor     dx, dx
        div     bx
; Делим число на десять. В остатке получается последняя цифра.
; Сразу выводить её нельзя, поэтому сохраним её в стэке.
        push    dx
        inc     cx
; А с частным повторяем то же самое, отделяя от него очередную
; цифру справа, пока не останется ноль, что значит, что дальше
; слева только нули.
        test    ax, ax
        jnz     short @oi2
; Теперь приступим к выводу.
        mov     ah, 02h
@oi3:   pop     dx
; Извлекаем очередную цифру, переводим её в символ и выводим.
        add     dl, 30h
        int     21h
; Повторим ровно столько раз, сколько цифр насчитали.
        loop    @oi3
	
	; переводим строку после выведенного числа
	mov ah, 9
	mov dx, offset NL
	int 21h

        pop     ax
        pop     bx
        pop     dx
        pop     cx
        ret
outint  endp
С этими изменениями программа прекрасно отрабатывает:
F:\Asm30>trapece
2.5912
20
2.5898
40
2.5896
60
2.5895
80

F:\Asm30>

 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 

Сообщений в этой теме
Hey   Ошибка в программе вычисления интеграла   7.09.2012 20:32
IUnknown   А ты в дебаггере посмотрел, что именно грузится в ...   8.09.2012 12:00
Hey   Спасибо, с тем фрагментом действительно пошло. Гд...   9.09.2012 12:30
TarasBer   А почему всё-таки fild пятёрки загрузил 8397?   9.09.2012 14:31
Hey   Снова загвоздка: не принимает директиву loop, попр...   9.09.2012 17:30
IUnknown   Это особенности цикла LOOP. Чтобы он работал, надо...   9.09.2012 18:14
Hey   P.S. ТОчно, забыл на счетчик СХ поставить. Правда,...   9.09.2012 18:31
IUnknown   С описанием x dd 2.0 все итерации проходят (прове...   9.09.2012 19:04
Hey   С описанием x dd 2.0 все итерации проходят (пров...   9.09.2012 21:08
Hey   Опять вынужден обратиться: программу продолжил, но...   10.09.2012 16:48
IUnknown   Во-первых, с чего ты решил, что вот это: сработает...   10.09.2012 20:12
IUnknown   Вот первоначальный вариант (можно еще дорабатывать...   11.09.2012 16:14
Hey   Однако серьезно! Буду пробовать. Признателен) ...   11.09.2012 21:54
Hey   Цикл ему кажется слишком длинным: на инструкции lo...   12.09.2012 18:11
IUnknown   Ты б за структурой следил, и вторую процедуру запи...   12.09.2012 23:10
Hey   Да, фрагмент с exit'ом я не туда вставил. Дейс...   13.09.2012 14:32
IUnknown   Это для перевода строки: NewLine, символ CR = 13, ...   13.09.2012 15:09
Hey   Решительно не хватает знаний, чтобы успешно заверш...   14.09.2012 20:22
IUnknown   Hey, я опять не понял, зачем тебе 2 цикла, в каждо...   15.09.2012 11:30
Hey   IUnknown, ты прав: уперся я в свое решение как лун...   15.09.2012 17:36
IUnknown   Еще вопрос: в какой программе ты набираешь листинг...   15.09.2012 18:24
Hey   Отлично, спасибо))   15.09.2012 19:12
Hey   IUnknown, опять вынужден обратиться. Та же многост...   5.10.2012 22:47
Hey   Порядок, нашел ошибки. Из процедуры SIN надо было ...   8.10.2012 15:55


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

 

- Текстовая версия 26.07.2025 14:01
Хостинг предоставлен компанией "Веб Сервис Центр" при поддержке компании "ДокЛаб"