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 
 К началу страницы 
+ Ответить 
 
 Ответить  Открыть новую тему 
Ответов
Hey
сообщение 14.09.2012 20:22
Сообщение #2


Новичок
*

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

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


Решительно не хватает знаний, чтобы успешно завершить программу. Я ее расширил, чтобы n возрастало до тех пор, пока не будет достигнута требуемая точность (0.0001). Вместо вывода значения функции при каждом из n (20, 40, 60 ....) прога выводит окончательное значение, причем не один раз((. Вывод n также не работает. Прилагаю.



.286p
.model small
.stack 100h
.data
mes db 'Operands not comparable', 13, 10, '$'
a dw 2
b dw 5
x dq 2.0
n dw 0
d dw 20
eps dd 0.0001
h dq ?
y dq ?
z dq ?
NL db 0Dh, 0Ah, "$"


.code
	
CalcF macro; На вершине стека д.б. параметр
	fld1
	fld st(1)
	fyl2x
	fldln2
	fmul
	fld1
	fdivr 
	
	endm
	
iCalcF macro param
	fld1
	fild param
	
	fyl2x
	fldln2
	fmul
	fld1
	fdivr 
	
	endm

Сalc_h macro
        mov cx, n
	add cx, d
	mov n, cx
	dec cx
	
	; вычисляем шаг
	finit
	fild b
	fisub a
	fidiv n
	fst h		; Сохраняем шаг
        endm

main proc

	mov ax, @data
	mov ds, ax
	           
outer_:
	С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
	fadd y
	fstp y	; Сохраняем измененное 

значение интеграла
	loop inner_loop
	
	fld y
	fmul h	
        
        call outfloat
        call OutInt ;выводим актуальное n
        finit

; далее повторяем с начала, но сохраняем в z для последующего сравнения с y
         
        Сalc_h 
	iCalcF b	; 1 / ln b
	fstp z
	iCalcF a	; 1 / ln a
	fadd z	; Складываем
	fdiv x	; Делим сумму на 2
	fstp z	; Сохр. начальное приближение
	fld x	;  

lesser_loop:
	fadd h	; X <- X + h
	CalcF
	fadd z
	fstp z	; Сохраняем измененное значение интеграла
	loop lesser_loop
	
	fld z
	fmul h	

        call outfloat
        
        call OutInt ;выводим актуальное n
        
        fld z
        fsub y
        fabs
        fcomp eps
        fstsw ax
        sahf

jp m2
jz m1
jc exit
jmp outer_
 
m1: jmp outer_ 
         
m2:
MOV DX, offset mes
mov Ah,09
int 21h


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


OutInt proc near
    xor ax,ax
    mov ax,n
    xor cx, cx
    mov  bx, 10
l1:
    xor     dx,dx
    div     bx
    push    dx
    inc     cx
    test ax, ax
    jnz l1
    mov ah, 02h
l2:    
    pop dx 
    loop l2    

    mov AH,9
    mov dx, offset NL    
    int 21h   
 ret
    outint endp


	outfloat proc   near ;вывод числа 
        push    ax
        push    cx
        push    dx

        push    bp
        mov     bp, sp
        push    10
        push    0
; Проверяем число на знак, и если оно 

отрицательное,
        ftst
        fstsw   ax
        sahf
        jnc     @of1
; то выводим минус
        mov     ah, 02h
        mov     dl, '-'
        int     21h
; и оставляем модуль числа.
        fchs

@of1:   fld1                           
        fld     st(1)                  
        fprem                         
        fsub    st(2), st              
        fxch    st(2)                 
 
        xor     cx, cx

@of2:   fidiv   word ptr [bp - 2]     
        fxch    st(1)                  
        fld     st(1)                  
        fprem                          
        fsub    st(2), st              
        fimul   word ptr [bp - 2]      
        fistp   word ptr [bp - 4]     
        inc     cx
        push    word ptr [bp - 4]
        fxch    st(1)                  
        ftst
        fstsw   ax
        sahf
        jnz     short @of2
; Теперь выведем её.
        mov     ah, 02h
@of3:   pop     dx
        add     dl, 30h
        int     21h
; И так, пока не выведем все цифры.
        loop    @of3                  
; Теперь за дробную часть, для начала 

;проверив её существование.
        fstp    st(0)                 
        fxch    st(1)                  
        ftst
        fstsw   ax
        sahf
        jz      short @of5
; Если она  ненулевая, выведем точку
        mov     ah, 02h
        mov     dl, '.'
        int     21h
; и не более четырех цифр дробной части.
        mov     cx, 4
; Помножим дробную часть на десять,
@of4:   fimul   word ptr [bp - 2]      
        fxch    st(1)                  
        fld     st(1)                  
; отделим целую часть 
        fprem                          
; оставим от произведения лишь дробную 

часть,
        fsub    st(2), st              
        fxch    st(2)                  
; сохраним полученную цифру во временной 

ячейке
        fistp   word ptr [bp - 4]      
; и сразу выведем.
        mov     ah, 02h
        mov     dl, [bp - 4]
        add     dl, 30h
        int     21h
; Теперь, если остаток дробной части 

ненулевой
        fxch    st(1)                  
        ftst
        fstsw   ax
        sahf
; и мы вывели менее четырех цифр, продолжим.
        loopnz  @of4                   
;  число выведено. Осталось убрать мусор из 

стэка.
@of5:   fstp    st(0)                  
        fstp    st(0)                  

        leave

        mov AH,9
        mov dx, offset NL
        int 21h

        pop     dx
        pop     cx
        pop     ax
        ret
outfloat endp

end main


 Оффлайн  Профиль  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

 

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