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