Теперь приведем два примера, использующих программу индикации  чисел с плавающей точкой.  Первый пример - решение квадратного  уравнения.  Найдем корни уравнения, задаваемого следующей формулой

  0 = A*X**2 + B*X + C

Из школьного курса математики известно, что решение этого  уравнения

  X = ( -B +- SQR( B**2 - 4*A*C))/(2*A)

Программа решения этого уравнения очевидна и показана на  Фиг. 7.26.  В ней предполагается, что все три параметра A, B и C  записаны в виде целых чисел.  Конечно, если вы будете использовать  программу не только как пример, нужно организовать процедуру ввода  различных коэффициентов.

          Microsoft (R) Macro Assembler Version 5.00              1/1/80 04:04:54

          Фиг. 7.26 Вычисление корней квадратного уравнения            Page   1-1

 

                                         PAGE   ,132

                                         TITLE  Фиг. 7.26 Вычисление корней квадратного уравнения

 

           0000                   STACK  SEGMENT STACK

           0000  0040[                  DW      64 DUP (?)

                  ????

                              ]

 

            0080                   STACK  ENDS

 

           0000                   CODE   SEGMENT

                                         ASSUME CS:CODE,DS:CODE,ES:CODE

                                         EXTRN  FLOAT_ASCII:NEAR

           0000  0001             A          DW      1

           0002  FFFB             B          DW      -5

           0004  0006             C          DW      6

           0006  ????             STATUS  DW     ?

           0008  0004             FOUR    DW     4

           000A  0002             TWO     DW     2

           000C  8C AD A8 AC EB A5 20     ERROR_MSG       DB     'Мнимые корни',10,13,'$'

               AA AE E0 AD A8 0A 0D

               24

           001B                   QUADRATIC         PROC   FAR

           001B  1E                          PUSH    DS        ; Сохранение адреса возврата

           001C  2B C0                  SUB     AX,AX

           001E  50                          PUSH    AX

           001F  8C C8                  MOV     AX,CS

           0021  8E D8                  MOV     DS,AX

           0023  8E C0                  MOV     ES,AX

 

           0025  9B DB E3                     FINIT             ;-----ST(0)-----;-----ST(1)------

           0028  9B DF 06 0002 R             FILD    B               ; B        ; ?

           002D  9B D8 8E 0000               FMUL    ST(0)           ; B**2      ; ?

           0032  9B DF 06 0000 R             FILD    A               ; A        ; B**2

           0037  9B DE 0E 0008 R             FIMUL   FOUR      ; 4*A      ; B**2

           003C  9B DE 0E 0004 R             FIMUL   C               ; 4*A*C          ; B**2

           0041  9B DE E1                     FSUBRP ST(1),ST(0)    ; D=B**2-4*A*C  ; ?

           0044  9B D9 E4                     FTST

           0047  9B DD 3E 0006 R             FSTSW   STATUS

           004C  9B                          FWAIT

           004D  8A 26 0007 R                MOV     AH,BYTE PTR STATUS+1

           0051  9E                          SAHF

           0052  72 37                  JB      IMAGINARY

           0054  9B D9 FA                     FSQRT             ; SQR(D)          ;

 

         Фиг. 7.26 Вычисление корней квадратного уравнения (начало)

           0057  9B D9 C0                     FLD     ST(0)          ; SQR(D)          ; SQR(D)

           005A  9B D9 E0                     FCHS              ; -SQR(D)         ; SQR(D)

           005D  9B DE 06 0002 R             FIADD   B               ; B-SQR(D)      ; SQR(D)

           0062  9B D9 E0                     FCHS              ; -B+SQR(D)     ; SQR(D)

           0065  9B D9 C9                     FXCH    ST(1)          ; SQR(D)          ; -B+SQR(D)

           0068  9B DE 06 0002 R             FIADD   B               ; B+SQR(D)      ; -B+SQR(D)

           006D  9B D9 E0                     FCHS              ; N1=-B-SQR(D)  ; N2=-B+SQR(D)

           0070  9B DE 36 0000 R             FIDIV   A               ; N1/A      ; N2

           0075  9B DE 36 000A R             FIDIV   TWO       ; ROOT1=N1/2*A  ; N2

           007A  E8 0000 E                    CALL   FLOAT_ASCII     ; N2        ; ?

           007D  9B DE 36 0000 R             FIDIV   A               ; N2/A      ; ?

           0082  9B DE 36 000A R             FIDIV   TWO       ; ROOT2=N2/2*A  ; ?

           0087  E8 0000 E                    CALL   FLOAT_ASCII     ; ?        ; ?

           008A  CB                           RET

           008B                   IMAGINARY:

           008B  8D 16 000C R                LEA     DX,ERROR_MSG

           008F  B4 09                  MOV     AH,9H

           0091  CD 21                  INT     21H       ; Вывод сообщения об ошибке

           0093  CB                           RET

           0094                   QUADRATIC         ENDP

           0094                   CODE   ENDS

                                         END    QUADRATIC

Фиг. 7.26 Вычисление корней квадратного уравнения (продолжение)

В примере отсутствует обработка комплексных чисел, но имеется  проверка дискриминанта (B**2 - 4*A*C) на отрицательность, и если это  число отрицательно, программа завешается с сообщением об ошибке.  Можно было бы ввести в программу комплексную арифметику, тем не  менее, ее нет в данном примере.  Необходимо помнить, что  сопроцессор 8087 не обрабатывает автоматически комплексные или  мнимые числа, и нужно писать программу раздельной обработки  действительной и мнимой частей комплексного числа.

Команда FTST проверяет дискриминант на отрицательность; она  подобна сравнению с встроенным нулевым операндом источника.  Программа записывает слово состояния в память, а затем загружает  его в регистр флагов микропроцессора 8088.  После этого делается проверка JB (переход, если меньше), определяющая, меньше ли нуля  дискриминант.  Оставшаяся часть программы проделывает работу по  вычислению двух корней уравнения, и здесь используется то  преимущество, что коэффициенты находятся в памяти.  Такой подход  минимизирует объем используемого в сопроцессоре 8087 стека.  Но  если вы переделаете эту программу так, что она будет подпрограммой,  вызываемой из другой программы, вам, вероятно, захочется передавать  параметры ей с помощью стека сопроцессора 8087.  В этом случае  потребуется другой способ для загрузки подпрограммой некоторых  величин.