Команды сканирования и сравнения



Команды сканирования и сравнения


    Две оставшиеся строковые команды используются в программах для
    сравнения строковой информации.  Первая из них - команда,
    сканирование строки SCAS.  Эта команда сравнивает значение в
    регистре AL или регистре AX с операндом в памяти, на который
    ссылается пара регистров ES:DI.  Команда SCAS устанавливает флаги
    нуля, переноса и переполнения, показывая результат сравнения
    аккумулятора и ячейки памяти, и изменяет регистр DI так, чтобы он
    указывал на следующий операнд в строке.
 
      Команда SCAS не может использовать обычный префикс REP для
    сканирования длинной строки информации. Точно так же, как команда
    REP LODS не имеет смысла, команда REP SCAS не позволяет программе
    контролировать каждое сравнение. Вместо этого существует два
    варианта префикса REP - "повторять пока равно" REPE и "повторять
    пока не равно" REPNE. Как и в случае обычного префикса REP,


    программа загружает в регистр CX длину строки. Если указан префикс
    REPE, команда выполняется ло тех пор, пока содержимое регистра AL
    (или AX) не перестанет совпадать с ячейками памяти, или пока
    содержимое регистра CX не станет равно 0. Пока аккумулятор
    совпадает с ячейкой памяти, сканирование продолжается. Команда
    REPNE в точности противоположна команде REPE. Сканирование
    продолжается до тех пор, пока аккумулятор не совпадает с ячейкой
    памяти.
 
      Комбинация команд SCAS и REPNE позволяет программе выполнять
    быстрый поиск по таблице. Чтобы найти объект в таблице, программа
    должна перебрать каждую ячейку для сравнения с аргументом. На
   Фиг. 4.24 показано, как команда SCAS выполняет эту функцию. В
    регистре AL содержится аргумент сравнения. Таблица SCAN_TABLE
    содержит значения, среди которых ведется поиск, а в регистре CX
    находится длина таблицы. Команда REPNE SCASB сканирует таблицу до
    тех пор, пока содержимое аккумулятора не станет равно элементу
    строки. В этом месте регистр DI указывает на байт таблицы,
    непосредственно следующий за сравнением. Вы можете определить
    смещение совпавшего объекта, вычитая единицу из регистра DI после
    метки FOUND. Программа может использовать эту информацию для
    доступа к другой таблице, или таблицам, которые содержат
    информацию, соответствующую этим исходным данным. Нужно обратить
    особое внимание на команду JE после команды сканирования.
    Существуют два случая, в которых управление передается этой
    команде: байт в строке совпал с регистром AL и условие, задаваемое
    префиксом REPNE, больше не выполняется; либо регистр CX достиг
    нулевого значения без нахождения соответствующего числа в таблице.
    В некоторых случаях создаются ситуации, исключающие появление
    второго условия. Но в большинстве программ, необходимо учитывать
    возможность неверных исходных данных. Программа перейдет на метку
    FOUND после команды сканирования, если команда установила флаг нуля
    (или равенства). Тем самым гарантируется, что сравнение найдено.
    Если же регистр CX достиг нуля, последняя итерация сканирования
    сбросила флаг нуля, показывая, что соответствия нет.

           Microsoft (R) Macro Assembler Version 5.00              1/1/80 04:01:36
           Фиг. 4.24 Поиск в таблице                              Page   1-1
 
 
                                         PAGE    ,132
                                         TITLE   Фиг. 4.24 Поиск в таблице
            0000                   CODE    SEGMENT
                                         ASSUME  CS:CODE,DS:CODE,ES:CODE
 
                                   ;--------------------------------------
                                   ; Поиск значения AL в таблице
                                   ;--------------------------------------
 
            0000  8D 3E 000C R                 LEA     DI, SCAN_TABLE        ; Адрес таблицы
            0004  B9 000B 90                   MOV     CX, SCAN_TABLE_LENGTH   ; Длина таблицы
            0008  F2/ AE                 REPNE   SCASB                       ; Поиск
            000A  74 00                  JE      FOUND                 ; Если равно, то значение найдено
                                   ; ...                         ; Иначе значение не найдено
            000C                   FOUND:
                                   ;-----  продолжение программы
 
            000C  89 96 93 8A 85 8D 83     SCAN_TABLE      DB      'ЙЦУКЕНГШЩЗХ'
                98 99 87 95
 
            = 000B                       SCAN_TABLE_LENGTH       EQU     $-SCAN_TABLE
 
            0017                   CODE    ENDS
                                         END
 
            Фиг. 4.24 Сканирование таблицы
      Последняя строковая команда - сравнение строк CMPS. Подобно
    сканированию строки, это - команда сравнения. Подобно команде MOVS,
    она работает с двумя операндами памяти. Команда CMPS сравнивает
    строку по адресу DS:SI со строкой по адресу ES:DI, и соответственно
    устанавливает флаги. Как и для команды SCAS, в данном случае
    использовать префикс REP нельзя, а префиксы REPE и REPNE можно
    использовать беспрепятственно.

          Microsoft (R) Macro Assembler Version 5.00              1/1/80 04:01:41
          Фиг. 4.25 Сравнение строк                         Page  1-1
 
                                        PAGE    ,132
                                        TITLE   Фиг. 4.25 Сравнение строк
           0000                   CODE    SEGMENT
                                        ASSUME  CS:CODE,DS:CODE,ES:CODE
 
                                  ;--------------------------------------
                                  ; Сравнивается 5-символьная строка с таблицей
                                  ; таких 5-символьных строк. Выход из программы
                                  ; если найдена искомая строка в таблице строк.
                                  ;--------------------------------------
 
           0000                   FIG4_25 PROC    NEAR
           0000  8D 36 001D R                 LEA     SI, ARGUMENT          ; Адрес строки
           0004  8D 3E 0022 R                 LEA     DI, COMPARE_TABLE     ; Адрес таблицы
           0008  BB 0000                      MOV     BX, 0           ; В BX cчетчик просмотренных строк
           000B                   COMPARE_LOOP:
           000B  56                           PUSH    SI                    ; Сохранение адреса строки
           000C  57                           PUSH    DI                    ; Сохранение адреса таблицы
           000D  B9 0005                      MOV     CX, 5           ; Сравниваются 5 байт
           0010  F3/ A6           REPE    CMPS    ARGUMENT,COMPARE_TABLE  ; Сравнение
           0012  5F                           POP     DI                    ; Восстановление
           0013  5E                           POP     SI                    ;  регистров
           0014  74 06                  JE          FOUND             ; Искомая строка найдена
           0016  83 C7 05                     ADD     DI, 5           ; Сдвиг указателя на следующую
                                                                ;  строку в таблице
           0019  43                           INC     BX                    ; Номер текущей строки в таблице
           001A  EB EF                  JMP     COMPARE_LOOP          ; Цикл
 
           001C                   FOUND:
           001C  C3                           RET
           001D                   FIG4_25 ENDP
 
           001D  41 42 43 44 45         ARGUMENT          DB          'ABCDE'
           0022                   COMPARE_TABLE   LABEL   BYTE
           0022  51 57 45 52 54 50 4F         DB          'QWERT','POIUY','ASDFG','LKJHG'
               49 55 59 41 53 44 46
               47 4C 4B 4A 48 47
           0036  5A 58 43 56 42 4D 4E         DB          'ZXCVB','MNBVC','VWXYZ','ABCDE'
               42 56 43 56 57 58 59
               5A 41 42 43 44 45
           004A                   CODE    ENDS
                                        END
 
            Фиг. 4.25 Сравнение строк
      Фиг. 4.25 демонстрирует пример использования команды CMPS.
    Этот пример сравнивает пятисимвольную исходную строку с таблицей
    строк символов. Программа пытается найти соответствие исходной
    строки с элементом таблицы. Когда строка найдена, в регистре BX
    нахолится индекс строки. В программе используется префикс REPE, так
    что команда сравненния строк выполняется до тех пор, пока один из
    символов аргумента не совпадает с символом таблицы. Если все пять
    символов совпали, программа находит правильный элемент. Команда JE
    ("переход, если равно") проверяет результат команды CMPS. Если
    сравнение завершилось из=за несоответствия символов, флаг нуля
    показывает ненулевое состояние. Если же команда CMPS завершилась
    потому, что счетчик CX стал нулевым, флаг нуля покажет совпадение и
    произойдет переход на метку FOUND. Вы можете заметить, что в этом
    примере отсутствуют некоторые необходимые детали, которые смогли бы
    сделать его хорошей программой. Например, он никак не обрабатывает
    случай, когда исходная строка не совпала ни с одним элементм
    таблицы. Любой хороший программист скажет вам, что исключительные
    ситуации нужно обрабатывать всегда.




Содержание раздела