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

Индекс материала
Турбо Ассемблер 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
Все страницы
     ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД

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

     ЪДДДДДДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї
     іТип возвращаемого значенияі Где находится возвращаемое значениеі
     ГДДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДґ
     і unsigned char            і                AX                  і
     і char                     і                AX                  і
     і enum                     і                AX                  і
     і unsigned short           і                AX                  і
     і short                    і                AX                  і
     і unsigned int             і                AX                  і
     і int                      і                AX                  і
     і unsigned long            і                DX:AX               і
     і long                     і                DX:AX               і
     і float                    і  регистр вершины стека сопроцессораі
     і                          і  8087 (ST(0))                      і
     і double                   і  регистр вершины стека сопроцессораі
     і                          і  8087 (ST(0))                      і
     і long double              і  регистр вершины стека сопроцессораі
     і                          і  8087 (ST(0))                      і
     і near*                    і                AX                  і
     і far*                     і                DX:AX               і
     АДДДДДДДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

          В общем случае 8- и 16-битовые значения возвращаются  в  ре-
     гистре  AX,  а 32-битовые значения - в AX:DX (при этом старшие 16
     бит значения находятся в регистре DX).  Значения с плавающей точ-
     кой возвращаются в регистре ST(0), который представляет собой ре-
     гистр вершины стека сопроцессора 8087 или  эмулятора сопроцессора
     8087, если используется эмулятор операций с плавающей точкой.

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

          Со структурами дело обстоит  несколько  сложнее.  Структуры,
     имеющие длину 1 или 2 байта, возвращаются в регистре AX, а струк-
     туры длиной 4 байта - в регистрах AX:DX. Трехбайтовые структуры и
     структуры,  превышающие 4 байта должны храниться в области стати-
     ческих данных, при этом должен возвращаться указатель на эти ста-
     тические данные. Как и все указатели, указатели на структуры, ко-
     торые  имеют  ближний тип (NEAR),  возвращаются в регистре AX,  а
     указатели дальнего типа - в паре регистров AX:DX.

          Давайте рассмотрим вызываемую  из  программы  на  языке  С++
     функцию на Ассемблере с малой моделью памяти FindLastChar,  кото-
     рая возвращает указатель на последний символ передаваемой строки.
     На языке С++ прототип этой функции выглядел бы следующим образом:

          extern char * FindLastChar(char * StringToScan);

     где StringToScan - это непустая строка, для которой должен  возв-
     ращаться указатель на последний символ.

          Функция FindLastChar имеет следующий вид:

                       .MODEL  SMALL
                       .CODE
                       PUBLIC _FindLastChar
     _FindLastChar            PROC
                       push  bp
                       mov   bp,sp
                       cld             ; в строковой инструкции нужно
                                       ; выполнять отсчет в прямом
                                       ; направлении
                       mov   ax,ds
                       mov   es,ax     ; теперь ES указывает на
                                       ; ближний сегмент данных
                       mov   di,       ; теперь ES:DI указывает на
                                       ; начало передаваемой строки
                       mov   al,0      ; найти нулевой символ,
                                       ; завершающий строку
                       mov   cx,0ffffh ; работать в пределах
                                       ; 64К-1 байт
                       repne scasb     ; найти нулевой символ
                       dec   di        ; установить указатель
                                       ; обратно на 0
                       dec   di        ; ссылка обратно на
                                       ; последний символ
                       mov   ax,dx     ; возвратить в AX указатель
                                       ; ближнего типа
                       pop   bp
                       ret
     _FindLastChar     ENDP
                       END

          Конечный результат, указатель на передаваемую строку,  возв-
     ращается в регистре AX.

     Турбо Ассемблер 3.0/tasm/#2-2                             = 104 =


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


          Теперь мы рассмотрим пример программы на Borland C++,  вызы-
     вающей  функцию  Турбо  Ассемблера.   Модуль   Турбо   Ассемблера
     COUNT.ASM содержит функцию LineCount, которая возвращает значение
     счетчика числа строк и символов в передаваемой строке:

     ; Вызываемая из С++ функция на Ассемблере с малой моделью памяти
     ; для подсчета числа строк и символов в завершающейся нулем
     ; "строке".
     ;
     ; Прототип функции:
     ;      extern unsigned int LineCount(char * near StringToCount,
     ;             unsigned int near * CharacterCountPtr);
     ;
     ; Ввод:
     ;      char near * StringToCount: указатель на "строку", в
     ;      которой нужно выполнить подсчет строк.
     ;
     ;      unsigned int near * CharacterCountPtr: указатель на
     ;      целую переменную, в которую нужно записать значение
     ;      счетчика
     NEWLINE      EQU   0ah        ; символ перевода строки в Си
                  .MODEL  SMALL
                  .CODE
                  PUBLIC  _LineCount
     __LineCount   PROC
                  push  bp
                  mov   bp,sp
                  push  si         ; сохранить регистровую
                                   ; переменную вызывающей
                                   ; программы
                  mov   si,[bp+4]  ; SI указывает на строку
                  sub   cx,cx      ; установить значение
                                   ; счетчика символов в 0
                  mov   dx,cx      ; установить в 0 счетчик
                                   ; строк
     LineCountLoop:
                  lodsb            ; получить следующий символ
                  and   al,al      ; это 0? конец строки?
                  jz    EndLineCount ; да, выполнено
                  inc   cx         ; нет, подсчитать следующий
                                   ; символ
                  cmp   al,NEWLINE ; это новая строка?
                  jnz   LineCountLoop ; нет, проверить
                                   ; следующий символ
                  inc   dx         ; да, подсчитать еще одну
                                   ; строку
                  jmp   LineCountLoop
     EndLineCount:
                  inc   dx         ; подсчитать строку, которая

     Турбо Ассемблер 3.0/tasm/#2-2                             = 105 =

                                   ; завершается нулевым символом
                  mov   [bx],cx    ; задать значение переменной-
                                   ; счетчика
                  mov   ax,dx      ; возвратить счетчик строк в
                                   ; качестве значения счетчика
                  pop   si         ; восстановить регистровую
                                   ; переменную вызывающей
                                   ; программы
                  pop   bp
                  ret
     _LineCount         ENDP
                  END

          Следующий модуль на языке С++ с именем CALLCT.CPP  представ-
     ляет собой пример вызова функции LineCount:

          char * TestString="Line 1\nline 2\nline 3";
          extern "C" {
                 unsigned int LineCount(char * StringToCount,
                 unsigned int near * CharacterCountPtr); }
          main()
          {
             unsigned int LCount;
             unsigned int CCount;

             Lcount = LineCount(TestString, &CCount);
             printf("Lines: %d\nCharacters: %d\n", LCount, CCount);
          }

          Два модуля компилируются и компонуются вместе с помощью  ко-
     мандной строки:

             bcc -ms callct.cpp count.asm

          Как здесь показано, функция LineCount будет работать  только
     при компоновке с программами на языке С++, в которых используется
     малая модель памяти,  так как в других моделях размеры указателей
     и адресов в  стеке  изменятся.  Приведем  пример  версии  функции
     LineCount (COUNTLG.ASM),  которая будет работать с программами на
     С++, использующим большую модель памяти (но не малую модель: пос-
     кольку передаются дальние указатель, функция LineCount также опи-
     сана, как функция дальнего типа):

     ; Вызываемая из С++ функция на Ассемблере для подсчета числа
     ; строк и символов в завершающейся нулем "строке".
     ;
     ; Прототип функции:
     ;      extern unsigned int LineCount(char * far StringToCount,
     ;             unsigned int far * CharacterCountPtr);
     ;