Консультация № 180947
26.11.2010, 03:13
0.00 руб.
26.11.2010, 15:12
0 5 1
Здравствуйте, уважаемые эксперты! Прошу Вас ответить на следующий вопрос:
Здравствуйте еще раз, помоги те пожалуйста с решением задачи, связанную с сопроцессорами
"Рассчитать и вывести значение выражения, при заданных пользователем значениях x и a." и пример:

Обсуждение

Неизвестный
26.11.2010, 15:04
общий
В какой среде программирования? Какая модель памяти? ...
Неизвестный
26.11.2010, 15:14
общий
Вывод, по-видимому, легче было сделать в MASM, где есть макросы для этого. В TASM можно сделать COM-файл, но выводить придется "ручками". Так-что ответ на первый вопрос просто необходим
А так, задача вычисления решаентся элементарно
Неизвестный
26.11.2010, 20:29
общий
На Тасме просят, через ком файл. Модель памяти не обговорено. Спасибо что вставили картинку. не понял как этого сделать.
давно
Посетитель
7438
7205
27.11.2010, 01:56
общий
Почему в формуле много констант?
Это обязательно? Или можно сначала упростить?
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
7438
7205
28.11.2010, 01:28
общий
это ответ
Здравствуйте, Алексей Патрин!
Вот Вам программа...
Считается все, как в формуле (без упрощений) ...
Код:

.model tiny, C
.data
sX db 'Enter x: $' ;приглашения для ввода
sA db 0ah,'Enter a: $'
sY db 0ah,'Y = $' ;результат
sAny db 0dh,0ah,'Press any key$'

x dq 0 ;переменные
a dq 0

num db 32 ;буфер для ввода строки
len db 0
String db 32 dup (0)

.code
.386
.startup
lea dx, sX
mov ah, 9
int 21h ;ждем Х

lea dx, num
mov ah, 0ah
int 21h

call str2float ;преобразуем строку в double
fstp x

lea dx, sA
mov ah, 9
int 21h ;ждем А

lea dx, num
mov ah, 0ah
int 21h

call str2float ;преобразуем строку в double
fstp a

call calcY, offset a, offset x ;считаем по формуле

call float2str ;преобразуем в строку
lea dx, sY
mov ah, 9
int 21h
lea dx, String ;выведем
mov ah, 9
int 21h

lea dx, sAny
mov ah, 9
int 21h ;ждем "any key"

mov ah, 8
int 21h

mov ax, 4c00h
int 21h

;експонента st=e^st
exp proc
fldl2e ;log(осн 2)e->st
fmulp ;st(1)*log(осн 2)e->st
fld st ;x*log[2]e->st(1)
frndint ;округляем st до целого
fsub st(1),st ;st(1)-=st
fxch ;st(1)<->st
f2xm1 ;st=(2 в степени st) - 1
fld1 ;1->st
fadd ;st+=1
fscale ;exp = st * (2 в степени st(1))
fstp st(1) ;чтобы убрать значение из st(1)
ret
exp endp

;считаем по формуле
y=(3*4+5*6-ae^x)/(7/2+4/3+12/3)*(16/2)*3*6*cos(a/x)
calcY proc pa:word, px:word
local c2:word, c3:word, c4:word, c5:word, c6:word, c7:word, c12:word, c16:word
uses di, si
mov di, pa ;адрес А
mov si, px ;адрес Х
mov c2, 2 ;константы
mov c3, 3
mov c4, 4
mov c5, 5
mov c6, 6
mov c7, 7
mov c12, 12
mov c16, 16

fild c3 ;3
fimul c4 ;3*4
fild c5 ;5
fimul c6 ;5*6
faddp ;3*4+5*6
fld qword ptr [si] ;x
call exp ;e^x
fmul qword ptr [di] ;a*e^x
fsubp st(1), st ;3*4+5*6-a*e^x

fild c7 ;7
fidiv c2 ;7/2
fild c4 ;4
fidiv c3 ;4/3
faddp ;7/2+4/3
fild c12 ;12
fidiv c3 ;12/3
faddp ;7/2+4/3+12/3

fdivp ;y=(3*4+5*6-a*e^x)/(7/2+4/3+12/3)

fimul c16 ;y*16
fidiv c2 ;y*16/2
fimul c3 ;y*16/2*3
fimul c6 ;y*16/2*3*6

fld qword ptr [di] ;a
fdiv qword ptr [si] ;a/x
fcos ;cos(a/x)
fmulp ;y*16/2*3*6*cos(a/x)
ret
calcY endp

;Преобразование строки в вещественное число в st сопроцессора
str2float proc ;преобразование строки в вещественное число
local ww:word ;для загрузки в сопроцессор
local dcount:word ;число знаков после точки
local wSign:word ;знак числа
local c10:word ;10

fldz ;подготовим st=0
lea si, String ;числовая строка
xor ax, ax ;0
mov dcount, ax ;число знаков после точки = 0
mov wSign, ax ;положительное
mov c10, 10 ;10
s2fStart: ;цикл обхода незначащих стартовых пробелов
lodsb
cmp al, 0dh
je s2fRet ;по концу строки - выход
cmp al, ' '
je s2fStart ;на повтор
cmp al, 9
je s2fStart
cmp al, '-'
jne s2fCompare ;все остальное - на анализ
inc wSign ;по минусу - взводим признак минуса
s2fNext:
lodsb ;очередной символ
s2fCompare:
cmp al, '.' ;точка
je s2fInc
cmp al, '0'
jb s2fSign ;все, что не цифры - конец числа
cmp al, '9'
ja s2fSign

and ax, 0fh ;иначе готовим разряд
mov ww, ax ; для загрузки в сопроцессор
cmp dcount, 0 ;если целая часть, то
je s2fMul10 ; на умножение на 10
mov cx, dcount ;иначе делим dcount раз на 10
fild ww ; очередной разряд
s2fdiv:
fidiv c10 ;делим dcount раз
loop s2fdiv
faddp ;складываем разряд за точкой с формируемым числом
s2fInc:
inc dcount ;для точки только увеличиваем dcount
jmp s2fNext ;пока не дойдем до конца

s2fMul10: ;целое число
fimul c10 ;умножаем старое на 10
fiadd ww ;и прибавляем очередной разряд
jmp s2fNext
s2fSign:
cmp wSign, 0 ;если bSign == 1
je s2fRet
fchs ;то меняем знак
s2fRet:
ret
str2float endp

;преобразование вещественного числа из st в строку по адресу String
float2str proc
local c10:word ;10
local wSign:word ;знак
local dig:word ;буфер для извлечения целого из сопроцессора
local sTemp:byte:64 ;временный буфер для строки

mov c10, 10 ;10
mov wSign, 0 ;пока считаем, что положительное
lea di, sTemp ;здесь будем формировать строку
ftst ;Проверяем число
fstsw ax ;флаги в ax
sahf ;флаги в регистре флагов
jnz f2s_notZero ;не 0
mov ax, '$0' ;если 0, то выводим 0
stosw
jmp f2s_Ret ;на выход

f2s_notZero: ;не 0
jnc f2s_1 ;если отрицательное,
inc wSign ; то помечаем минус
fchs ; и оставляем модуль числа.
; Пояснение далее пойдёт на примере. ; ST(0) ST(1) ST(2) ST(3) ...
; Отделим целую часть от дробной. ; 73.25 ...
f2s_1: fld1 ; 1 73.25 ...
fld st(1) ; 73.25 1 73.25 ...
; Остаток от деления на единицу даст дробную часть.
fprem ; 0.25 1 73.25 ...
; Если вычесть её из исходного числа, получится целая часть.
fsub st(2), st ; 0.25 1 73 ...
fxch st(2) ; 73 1 0.25 ...
; Сначала поработаем с целой частью. Считать количество цифр будем в CX.
xor cx, cx
; Поделим целую часть на десять,
f2s_2: fidiv c10 ; 7.3 1 0.25 ...
fxch st(1) ; 1 7.3 0.25 ...
fld st(1) ; 7.3 1 7.3 0.25 ...
; отделим дробную часть - очередную справа цифру целой части исходного числа,-
fprem ; 0.3 1 7.3 0.25 ...
; от чатсного оставим только целую часть
fsub st(2), st ; 0.3 1 7 0.25 ...
; и сохраним цифру
fimul c10 ; 3 1 7 0.25 ...
fistp dig ; 1 7 0.25 ...
inc cx
; в стеке.
push dig
fxch st(1) ; 7 1 0.25 ...
; Так будем повторять, пока от целой части не останется ноль.
ftst
fstsw ax
sahf
jnz f2s_2
; Теперь выведем её.
f2s_3: pop ax
; Вытаскиваем очередную цифру, переводим её в символ и выводим.
add al, 30h
stosb
; И так, пока не выведем все цифры.
loop f2s_3 ; 0 1 0.25 ...
; Итак, теперь возьмёмся за дробную часть, для начала проверив её существование.
fstp st(0) ; 1 0.25 ...
fxch st(1) ; 0.25 1 ...
ftst
fstsw ax
sahf
jz f2s_5
; Если она всё-таки ненулевая, выведем точку
lea ax, sTemp
mov cx, di
sub cx, ax
sub cx, 63
neg cx
mov al, '.'
stosb
; Помножим дробную часть на десять
f2s_4: fimul c10 ; 2.5 1 ...
fxch st(1) ; 1 2.5 ...
fld st(1) ; 2.5 1 2.5 ...
; отделим целую часть - очередную слева цифру дробной части исходного числа,-
fprem ; 0.5 1 2.5 ...
; оставим от произведения лишь дробную часть
fsub st(2), st ; 0.5 1 2 ...
fxch st(2) ; 2 1 0.5 ...
; сохраним полученную цифру во временной ячейке
fistp dig ; 1 0.5 ...
; и сразу выведем.
mov ax, dig
add al, 30h
stosb
; Теперь, если остаток дробной части ненулевой
fxch st(1) ; 0.5 1 ...
ftst
fstsw ax
sahf
; и мы вывели менее cx цифр, продолжим
loopnz f2s_4 ; 0 1 ...
; Итак, число выведено. Осталось убрать мусор из стека.
f2s_5: fstp st(0) ; 1 ...
fstp st(0) ; ...
mov byte ptr [di], '$'

; и скопировать в буфер String
lea si, sTemp
lea di, String
xor cx, cx ;длина
cmp wSign, 0 ;проверим на знак
je f2s_6
mov al, '-' ;отрицательное
stosb
f2s_6:
lodsb
stosb ;копируем 1 байт
inc cx ;считаем
cmp cx, 14 ;копируем только 14 байт !!! (если получится число
; с большим чем 14 байт знаков, то последние усекутся)
je f2s_7 ;насильно закрываем $!
cmp al, '$'
jne f2s_6 ;копирование завершаем по $
dec cx ;отнимем 1 (посчитался $)
f2s_7:
mov byte ptr [di], '$' ;закроем $ (для случая обрезания)
f2s_Ret:
ret
float2str endp

end
5
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Форма ответа