КОМПЬЮТЕРНАЯ ЛИТЕРАТУРА - Турбо Ассемблер 3.0/tasm/#2-2 - Стр. 29

Индекс материала
Турбо Ассемблер 3.0/tasm/#2-2
Стр. 2
Стр. 3
Стр. 4
Стр. 5
Стр. 6
Стр. 7
Стр. 8
Стр. 9
Стр. 10
Стр. 11
Стр. 12
Стр. 13
Стр. 14
Стр. 15
Стр. 16
Стр. 17
Стр. 18
Стр. 19
Стр. 20
Стр. 21
Стр. 22
Стр. 23
Стр. 24
Стр. 25
Стр. 26
Стр. 27
Стр. 28
Стр. 29
Стр. 30
Стр. 31
Стр. 32
Стр. 33
Стр. 34
Стр. 35
Стр. 36
Стр. 37
Стр. 38
Стр. 39
Стр. 40
Стр. 41
Стр. 42
Стр. 43
Стр. 44
Стр. 45
Стр. 46
Стр. 47
Стр. 48
Стр. 49
Стр. 50
Стр. 51
Стр. 52
Стр. 53
Стр. 54
Все страницы
          lea   bx,DestString              ; самый левый параметр
          lea   ax,SourceString            ; самый правый параметр
          call  strcpy pascal,bx,ax


     Турбо Ассемблер 3.0/tasm/#2-2                             = 114 =

          Турбо Ассемблер автоматически вставит команды помещения  ар-
     гументов в стек в последовательности, принятой в Паскале (сначала
     BX, затем AX), и выполнит вызов STRCPY (преобразуя имя к верхнему
     регистру, как принято в соглашениях Паскаля).

          В последнем случае конечно подразумевается, что вы  переком-
     пилировали  функцию strcpy с параметром -p, так как в стандартной
     библиотечной версии данной функции используются соглашения по вы-
     зову, принятые в С++, а не в Паскале.

          Функции С++  сохраняют следующие регистры (и только их): SI,
     DI,  BP, DS, SS, SP и CS. Регистры AX, BX, CX, DX, ES и флаги мо-
     гут произвольно изменяться.

              Вызов из Турбо Ассемблера функции Borland C++
     ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

          Одним из случаев,  когда вам может потребоваться вызвать  из
     Турбо Ассемблера функцию Borland C++,  является необходимость вы-
     полнения сложных вычислений,  поскольку вычисления гораздо  проще
     выполнять  на  С++,  чем на Ассемблера.  Особенно это относится к
     случаю смешанных вычислений, где используются и значения с плава-
     ющей точкой и целые числа.  Лучше возложить функции по выполнению
     преобразования типов и реализации арифметики с  плавающей  точкой
     на С++.

          Давайте рассмотрим  пример программы на Ассемблере,  которая
     вызывает функцию Borland C++, чтобы выполнить вычисления с плава-
     ющей точкой.  Фактически в данном примере функция Borland C++ пе-
     редает последовательность целых чисел другой  функции  Турбо  Ас-
     семблера,  которая  суммирует  числа  и  в  свою очередь вызывает
     другую функцию Borland C++ для выполнения вычислений  с плавающей
     точкой (вычисление среднего значения).

          Часть программы   CALCAVG.CPP,    реализованная    на    С++
     (CALCAVG.CPP), выглядит следующим образом:

          #include 
                                               ; значение
                         add   ax,2            ; ссылка на следующее
                                               ; значение
                         loop  AverageLoop
                         push  WORD PTR [bp+8] ; получить снова число
                                               ; значений, переданных
                                               ; в функцию IntDivide
                                               ; в правом параметре
                         push  ax              ; передать сумму в
                                               ; левом параметре
                         call  _IntDivide      ; вычислить среднее
                                               ; значение с плавающей
                                               ; точкой
                         add   sp,4            ; отбросить параметры
                         pop   bp
                         ret                   ; среднее значение в
                                               ; регистре вершины
                                               ; стека сопроцессора
                                               ; 8087

     Турбо Ассемблер 3.0/tasm/#2-2                             = 116 =

          _Average       ENDP
                         END

          Основная функция (main) на языке С++ передает  указатель  на
     массив  целых  чисел  TestValues и длину массива в функцию на Ас-
     семблере Average.  Эта функция вычисляет сумму целых чисел, а за-
     тем  передает эту сумму и число значений в функцию С++ IntDivide.
     Функция IntDivide приводит сумму и число значений к типу с плава-
     ющей точкой и вычисляет среднее значение (делая это с помощью од-
     ной строки на С++,  в то время как на Ассемблере для этого потре-
     бовалось бы несколько строк).  Функция IntDivide возвращает сред-
     нее значение (Average) в регистре вершины стека сопроцессора 8087
     и передает управление обратно основной функции.

          Программы CALCAVG.CPP  и  AVERAGE.ASM можно скомпилировать и
     скомпоновать в выполняемую программу CALCAVG.EXE с помощью коман-
     ды:

          bcc calcavg.cpp average.asm

          Отметим, что функция Average будет работать как с малой, так
     и  с большой моделью данных без необходимости изменения ее исход-
     ного кода, так как во всех моделях передается указатель  дальнего
     типа. Для поддержки больших моделей кода (сверхбольшой, большой и
     средней) пришлось бы только  изменить  соответствующую  директиву
     .MODEL.

          Пользуясь преимуществами расширений,  обеспечивающих незави-
     симость Турбо Ассемблера от языка, ассемблерный код из предыдуще-
     го примера можно записать более сжато (CONSISE.ASM):

             .MODEL  small,C
             EXTRN   C IntDivide:PROC
             .CODE
             PUBLIC  C Average
     Average        PROC C ValuePtr:DWORD, NumberOfValues:WORD
             les     bx,ValuePtr
             mov     cx,NumberOfValues
             mov     ax,0
     AverageLoop:
             add     ax,es:[bx]
             add     bx,2        ;установить указатель
                                 ;на следующее значение
             loop    AverageLoop
             call    _IntDivide C,ax,NumberOfValues
             ret
     Average        ENDP
             END




     Турбо Ассемблер 3.0/tasm/#2-2                             = 117 =

         Глава 19. Интерфейс Турбо Ассемблера с Турбо Паскалем
     ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

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

           Большинство программ,  которые вы захотите написать,  можно
     реализовать целиком на Турбо Паскале.  В отличие  от  большинства
     других  компиляторов  Паскаля,  Турбо Паскаль позволяет вам с по-
     мощью массивов Port[], Mem[], MemW[] и MemL[] непосредственно об-
     ращаться   ко  всем  ресурсам  компьютера,  а с помощью  процедур
     Intr() и MsDos() вы можете обращаться к базовой системе ввода-вы-
     вода (BIOS) и операционной системе.

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