Главная · Поиск книг · Поступления книг · Top 40 · Форумы · Ссылки · Читатели

Настройка текста
Перенос строк


    Прохождения игр    
Demon's Souls |#13| Storm King
Demon's Souls |#12| Old Monk & Old Hero
Demon's Souls |#11| Мaneater part 2
Demon's Souls |#10| Мaneater (part 1)

Другие игры...


liveinternet.ru: показано число просмотров за 24 часа, посетителей за 24 часа и за сегодня
Rambler's Top100
Образование - Питер Абель Весь текст 992.61 Kb

Ассемблер и программирование для IBM PC

Предыдущая страница Следующая страница
1 ... 24 25 26 27 28 29 30  31 32 33 34 35 36 37 ... 85
поля.  Программа включала три команды для инициализации и пять команд  для
цикла. Команда MOVS с префиксом REP и длиной в регистре CX может выполнять
пересылку любого числа символов более эффективно.
     Для области,  принимающей  строку,  сегментным  регистром,   является
pегистр ES,  а регистр DI содержит относительный адрес области, передающей
строку.  Сегментным регистром является регистр DS,  а регистр SI  содержит
относительный адрес.  Таким образом,  в начале программы перед выполнением
команды MOVS необходимо инициализировать регистр ES вместе с регистром DS,
а также загрузить требуемые относительные адреса полей в регистры DI и SI.
В зависимости от состояния флага DF команда MOV  S  производит  увеличение
или уменьшение на 1 (для байта) или на 2 (для слова) содержимого регистров
DI и SI.
     Приведем команды, эквивалентные цепочечной команде REP MOVSB:

                 JCXZ      LABEL2
     LABEL1:     MOV       AL,[SI]
                 MOV       [DI],AL
                 INC/DEC   DI        ;Инкремент или декремент
                 UNC/DEC   SI        ;Инкремент или декремент
                 LOOP      LABEL1
     LABEL2:     ...

     В программе на рис.11.1 процедура C10MVSB  использует  команду  MOVSB
для пересылки содержимого десятибайтового поля NAME1 в поле NAME2.  Первая
команда CLD сбрасывает флаг  направления  в  0  для  обеспечения  процесса
пересылки слева направо.  В нормальном  состоянии  флаг  DF  обычно  имеет
нулевое значение и команда CLD используется из предосторожности.

__________________________________________________________________________

        page    60,132
TITLE   STRING  (EXE)  Проверка строковых операций
; ---------------------------------------------------
STACKSG SEGMENT PARA STACK 'Stack'
        DW      32 DUP(?)
STACKG  ENDS
; ---------------------------------------------------
DATASG  SEGMENT PARA 'Data'
NAME1   DB      'Assemblers'    ;Элементы данных
NAME2   DB      10 DUP(' ')
NAME3   DB      10 DUP(' ')
DATASG  ENDS
; ---------------------------------------------------
CODESG  SEGMENT PARA 'Code'
BEGIN   PROC    FAR             ;Основная процедура
        ASSUME  CS:CODESG,DS:DATASG,SS:STACKSG,ES:DATASG
        PUSH    DS
        SUB     AX,AX
        PUSH    AX
        MOV     AX,DATASG
        MOV     DS,AX
        MOV     ES,AX
        CALL    C10MVSB         ;Подпрограмма MVSB
        CALL    D10MVSW         ;Подпрограмма LODS
        CALL    E10LODS         ;Подпрограмма LODS
        CALL    F10STOS         ;Подпрограмма CMPS
        CALL    H10SCAS         ;Подпрограмма SCAS
        RET
BEGIN   ENDP
;               Использование MOVSB:
;               -------------------
C10MVSB PROC    NEAR
        CLD
        LEA     SI,NAME1
        LEA     D1,NAME2
        MOV     CX,10           ;Переслать 10 байтов
        REP MOVSB               ; из NAME1 в NAME2
        RET
C10MVSB ENDP
;               Использование MOVSW:
;               -------------------
D10MVSW PROC    NEAR
        CLD
        LEA     SI,NAME2
        LEA     DI,NAME3
        MOV     CX,05           ;Переслать 5 слов
        REP MOVSW               ; из NAME2 в NAME3
        RET
D10MVSW ENDP
;               Использование LODSW:
;               -------------------
E10LODS PROC    NEAR
        CLD
        LEA     SI,NAME1        ;Загрузить первое слово
        LODSW                   ; из NAME1 в AX
        RET
E10LODS ENDP
;               Использование STOSW:
;               -------------------
F10STOS PROC    NEAR
        CLD
        LEA     D1,NAME3
        MOV     CX,05
        MOV     AX,2020H        ;Переслать пробелы
        REP STOSW               ; в NAME3
        RET
F10STOS ENDP
;               Использование CMPSB:
;               -------------------
G10CMPS PROC    NEAR
        CLD
        MOV     CX,10
        LEA     SI,NAME1
        LEA     DI,NAME2
        REPE CMPSB              ;Сравнить NAME1 и NAME2
        JNE     G20             ;Не равны?
        MOV     BH,01

G20:    MOV     CX,10
        LEA     SI,NAME2
        LEA     DI,NAME3
        REPE CMPSB              ;Сравнить NAME2 и NAME3
        JE      G30             ;Если равны, то выйти
        MOV     BL,02
G30:    RET
G10CMPS ENDP

;               Использование SCASB:
;               -------------------
H10SCAS PROC    NEAR
        CLD
        MOV     CX,10
        LEA     DI,NAME1
        MOV     AL,'m'          ;Поиск символа 'm'
        REPNE SCASB             ; в NAME1
        JNE     H20             ;Если не найден - выйти
        MOV     AH,03
H20:    RET
H10SCAS ENDP

CODES   ENDS
        END     BEGIN
__________________________________________________________________________

     Рис.11.1. Использование цепочечных команд.


     Две команды LEA загружают регистры SI и  DI  относительными  адресами
NAME1 и NAME2  соответственно.  Так  как  регистры  DS  и  ES  были  ранее
инициализированы адресом DATASG, то полные  адреса  полей  NAME1  и  NAME2
будут  в  регистрах  ES:DI  и  DS:SI.   (COM    программа    автоматически
инициализирует регистры ES  и  DS).  Команда  MOV  заносит  в  регистр  CX
значение 10 - длину полей NAME1  и  NAME2.  Команда  REP  MOVSB  выполняет
следующее:

          - Пересылает самый  левый  байт  из  поля  NAME1  (адресованного
     pегистрами  ES:DI)  в  самый  левый  байт  поля  NAME2 (адресованного
     регистрами DS:SI).
          - Увеличивает на 1 адреса в регистрах DI  и  SI  для  следующего
     байта.
          - Уменьшает CX на 1.
          - Повторяет перечисленные действия (в  данном  случае  10  раз),
     пока содержимое регистра CX не станет равным нулю.

     Поскольку флаг DF имеет нулевое значение, команда  MOVSB  увеличивает
адреса в регистрах DI и SI, и в каждой итерации процесс переходит на  байт
вправо, т.е. пересылает байт из NAME1+1 в NAME2+1 и т.д.  Если бы флаг  DF
был равен 1, тогда команда MOVSB уменьшала бы адреса в регистрах DI и  SI,
выполняя процесс справа  налево.  Но  в  этом  случае  регистры  SI  и  DI
необходимо инициализировать адресами последних байтов полей, т.е.  NAME1+9
и NAME2+9 соответственно.
     В  процедуре  D10MVSW  (рис.11.1)   используется    команда    MOVSW,
пересылающая  одно  слово  за  одно  выполнение.  Так  как  команда  MOVSW
увеличивает адреса в регистрах DS и SI на 2, операция требует только  пять
циклов.  Для процесса пересылки  справа  налево  регистр  SI  должен  быть
инициализирован адресом NAME1+8, а регистр DI - NAME2+8.


     LODS: ЗАГРУЗКА СТРОКИ
     ________________________________________________________________

     Команда LODS загружает из памяти в регистр AL один байт или в регистр
AX одно слово.  Адрес памяти определяется регистрами DS:SI. В  зависимости
от значения флага DF происходит увеличение или уменьшение регистра SI.
     Поскольку одна команда LODS загружает регистр, то практической пользы
от префикса REP в данном случае нет.  Часто простая команда MOV  полностью
адекватна команде LODS, хотя MOV генерирует три байта  машинного  кода,  а
LODS  -  только  один,  но  требует  инициализацию  регистра  SI.    Можно
использовать команду LODS в том случае, когда требуется продвигаться вдоль
строки (по байту или по слову), проверяя загружаемый регистр на конкретное
значение.
     Команды, эквивалентные команде LODSB:

               MOV  AL,[SI]
               INC  SI

     На рис.11.1 процедура  E10LODS  демонстрирует  использование  команды
LODSW.  В примере обрабатывается только одно слово: первый байт из области
NAME1 (содержащий As) заносится в регистр AL, а второй байт  -  в  регистр
AH. В результате в регистре AX получится значение sA.


     STOS: ЗАПИСЬ СТРОКИ
     ________________________________________________________________

     Команда STOS записывает (сохраняет) содержимое регистра AL или  AX  в
байте или в слове памяти.  Адрес памяти всегда  представляется  регистрами
ES:DI.  В зависимости от флага  DF  команда  STOS  также  увеличивает  или
уменьшает адрес в регистре DI на 1 для байта или на 2 для слова.
     Практическая польза команды STOS  с  префиксом  REP  -  инициализация
области данных конкретным значением, например, очистка дисплейного  буфера
пробелами. Длина области (в байтах или в cловах) загружается в регистр AX.
Команды, эквивалентные команде REP STOSB:

                    JCXZ      LABEL2
          LABEL1:   MOV       [DI],AL
                    INC/DEC   DI        ;Инкремент или декремент
                    LOOP      LABEL1
          LABEL2:   ...

     На рис.11.1 процедура  F10STOS  демонстрирует  использование  команды
STOSW.  Операция осуществляет запись  шест.  2020  (пробелы)  пять  раз  в
область NAME3, причем значение из регистра AL заносится в первый  байт,  а
из регистра AH - во второй.  По завершении  команды  регистр  DI  содержит
адрес NAME3+10.


     CMPS: СРАВНЕНИЕ СТРОК
     ________________________________________________________________

     Команда CMPS сравнивает содержимое одной области  памяти  (адресуемой
регистрами DS:SI) с содержимыми другой области (адресуемой как  ES:DI).  В
зависимости от флага DF  команда  CMPS  также  увеличивает  или  уменьшает
адреса в регистрах SI и DI на 1 для байта или на 2 для слова. Команда CMPS
устанавливает флаги AF, CF, OF, PF, SF и ZF.  При  использовании  префикса
REP в регистре CX должна находиться длина сравниваемых полей. Команда CMPS
может сравнивать любое число байт или слов.
     Рассмотрим процесс сравнения двух  строк,  содержащих  имена  JEAN  и
JOAN. Сравнение побайтно слева направо приводит к следующему:

               J  :  J        Равно
               E  :  O        Не равно (E меньше O)
               A  :  A        Равно
               N  :  N        Равно

     Сравнение  всех  четырех  байт  заканчивается  сравнением    N:N    -
pавно/нуль.  Так как имена "не равны", операция должна  прекратиться,  как
только будет обнаружено условие "не равно".  Для этих  целей  команда  REP
имеет модификацию REPE, которая  повторяет  сравнение  до  тех  пор,  пока
сравниваемые элементы равны, или регистр  CX  не  pавен  нулю.  Кодируется
повторяющееся однобайтовое сравнение следующим образом:

               REPE CMPSB

     На рис.11.1 в процедуре G10CMPS  имеются  два  примера  использования
команды CMPSB.  В первом примере происходит  сравнение  содержимого  полей
NAME1 и NAME2. Так как ранее команда MOVSB переслала содержимое поля NAME1
в поле NAME2, то команда  CMPSB  продолжается  на  всех  десяти  байтах  и
завершается  состоянием  pавно/нуль:  флаг  SF   получает    значение    0
(положительно) и флаг ZF - 1(нуль).
     Во втором примере сравнивается поля  NAME2  и  NAME3.  Ранее  команда
STOSW заполнила поле NAME3 пробелами,  поэтому  команда  CMPB  завершается
после сравнения первых же байт с  результатом  "больше/неравно":  флаг  SF
получает значение 0 (положительно) и флаг ZF - 0 (не нуль).
     Первый пример заканчивается с результатом "равно/нуль" и заносит 01 в
регистр BH.  Второй пример заканчивается с результатом "неравно" и заносит
02 в регистр BL.  При трассировке команд с помощью отладчика  DEBUG  можно
увидеть, что в конце процедуры G10CMPS регистр BX будет содержать значение
0102.
     Предупреждение!  Показанные  примеры  используют  команду  CMPSB  для
сравнения одного байта за одно выполнение. При использовании команды CMPSW
для  сравнения  одного  слова,  необходимо  инициализиpовать  регистр   CX
значением 5. Кроме того следует помнить, что команда CMPSW  при  сравнении
слов переставляет байты. Например, сравнивая имена SAMUEL и ARNOLD команда
CMPSW выбирает вместо SA и AR переставленные значения, т.е.  AS  и  RA.  В
результате  вместо  "больше"  получится  "меньше",    т.е.    неправильный
результат.  Таким образом команда  CMPSW  работает  правильно  только  при
Предыдущая страница Следующая страница
1 ... 24 25 26 27 28 29 30  31 32 33 34 35 36 37 ... 85
Ваша оценка:
Комментарий:
  Подпись:
(Чтобы комментарии всегда подписывались Вашим именем, можете зарегистрироваться в Клубе читателей)
  Сайт:
 
Комментарии (15)

Реклама