Как решить уравнение в ассемблере

Как правильно написать уравнение в assembler?

Пытаюсь вникнуть в assembler, но не могу понять почему в результате получаю кривую сцену?

  • Вопрос задан более трёх лет назад
  • 690 просмотров

Простой 6 комментариев

ладно, а что дальше происходит с результатом этого вычисления? он используется в качестве глубины? в смысле, если смотреть сверху на ваши странные объекты, то будет график этой функции?

если так, то может оно и правильно? при определённых значениях того fi, как раз такой зазубренный график и получается. просто мелко очень, растянуть надо бы

ну постройте график. я не знаю какой там у вас коэффициент fi.

если достаточно большой, то выглядит примерно так:

Как решить уравнение в ассемблере

Доброго здоров’ячка! Сегодня я расcкажу вам как решать квадратные уравнения с помощью сопроцесcора . Но, что это такое? Я не буду вдаваться в хардверные дебри, скажу только, что наряду с обычным процессором существует, так называемый, математический сопроцессор. Его функции ясны: чтобы не забивать основной процессор всякими math кодами (некоторые он может вычислить) есть математическая машина.

Математикам: я здесь покажу как программируется сопроцессор на основе решения квадратных уравнений.

Алгоритм решения:

  1. Мы имеем формулу общего квадратного уравнения (вспоминайте школу, класс этак восьмой :-). Она выглядит так: ax^2+bx+c=0
  2. Требуется найти ее дискриминант: D=b^2-4ac
  3. Если D то корней не существует, иначе п.4
  4. Если D=0 то есть один корень: X=-b/2a , иначе п.5
  5. Если D>0 то существуют два корня: X1=(-b-sqrt(D))/2a, X2=(-b+sqrt(D))/2a

С чего же начать? Ответ прост: с очистки математической машины. Почти все программы оставляют свои коды в сопроцессоре (для краткости будем называть его СП). Делается это одной коммандой: finit

Далее, найдем дискриминант:

Ну вот, D нашли. Теперь нужно его сравнить с нулем. Вот тут то и начинаются проблемы: у СП есть момент сравнивания и все, а мне нужно перейти на определенные «полки» программы. Зато у основного процессора (далее ОП) такая возможность есть, а значит, мне нужно перенести определенные флаги СП в ОП. Делается это так:

Теперь мы можем «попрыгать» по программе, но сначала таблица соответсвий:

УсловиеКоманда «прыжка»
jc j1
; если D то goto j1
jz j2
; если D = 0 то goto j2
; а если D > 0 то [далее]
finit
; опять очистили СП
fld temp2
; Введем в стек СП число temp2 (temp2=2)
fmul a
; Умножили temp2 на a
fld D
; Введем в стек СП дискриминант
fsqrt
; Посчитали корень даскриминанта
fld b
; Введем в стек СП число b
fchs
; Изменили знак у b
fsave temp2[4]
; Сохранили полное (регитры и стек) состояние СП (и стерли оное)
frstor temp2[4]
; Загрузили полное состояние
fsubr
; вычли корень дискриминанта из -b
fdivr
; первый корень
frstor temp2[4]
; Загрузили еще раз полное состояние
fadd
; сложили корень дискриминанта и -b
fdivr
; второй корень
jmp ex
; «прыгнули» на «выход»
; D j1:
mov ah, 09h
mov dx, offset mes1
int 21h
; вывели сообщение, что нет корней (под Win32)
jmp ex
; «прыгнули» на «выход»
; D = 0
; X = -b/(2*a)
j2:
finit
; опять очистили СП
fld temp2
; Введем в стек СП число temp2 (temp2=2)
fmul a
; Умножили temp2 на a
fld b
; Введем в стек СП число b
fdivr
; Разделили b на 2a
fchs
; Сменили знак
; Вот и единственный корень

Вот и все! Ошибок я не нашел (может Вы найдете). Можете вводить целые и дробные параметры — все равно получите правильный результат. Если у вас есть TASM (и за мелкими изменениями MASM ) то можете скачать данную программу.

При написании я частично пользовался книгой Юрова ASSEMBLER 2-е издание , за что ему большое спасибо!

Ну вот и все, что я хотел вам сказать. Бувайте!

Приложение 1. Полная программа на ASM

; >>>>>>>>>>>>>>>>
; Anton (Liloi) Moskalenko
; e-mail: liloi@mail.ru
; >>>>>>>>>>>>>>>>

; Create time & date: 15:55 14.08.2006

; Compiled with TASM 4.1

.286
.model small
.data

a dd 2.0
b dd 4.0
c dd 2.0
D dd ?

mes1 db ‘No roots! $’

temp dd 4.0
temp2 dd 2.0

.stack 256h
.code

;Main PROC
main proc

push @data
pop ds

; discriminante
; C++:
; D = sqr(b)-4*a*c

fld b
fmul b
fld a
fld temp

fmul
fld c
fmul
fsubp st(1),st(0)
fst D

fld temp2
fmul a
fld D
fsqrt
fld b
fchs

fsave temp2[4]
frstor temp2[4]

fsubr
fdivr ; first root

fadd
fdivr ; second root

int main(int argc, char *argv[])
<
const float a = 3, b = 2, c = -1;
float D = 0, x, x1, x2;


источники:

http://www.liloisproj.narod.ru/res_kv.htm