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