Сист. прогр. Ч2 (1085771), страница 2
Текст из файла (страница 2)
На рис.9.1 в процедуре G10CMPS имеется два примера использования команды CMPSB. В первом примере происходит сравнение содержимого полей NAME1 и NAME2. Так как ранее команда MOVSB переслала содержимое поля NAME1 в поле NAME2, то команда CMPSB продолжается по всем десяти байтам и завершается состоянием «равно/нуль»: флаг SF получает значение 0 (положительно) и флаг ZF - 1(нуль).
Во втором примере сравниваются поля NAME2 и NAME3. Ранее команда STOSW заполнила поле NAME3 пробелами, поэтому команда CMPSB завершается после сравнения первых же байтов с результатом "больше/не равно": флаг SF получает значение 0 (положительно) и флаг ZF - 0 (не нуль).
Первый пример заканчивается с результатом "равно/нуль" и заносит 01 в регистр ВН. Второй пример заканчивается с результатом "не равно" и заносит 02 в регистр BL. При трассировке команд с помощью отладчика DEBUG можно увидеть, что в конце процедуры G10CMPS регистр ВХ будет содержать значение 0102.
Предупреждение! Показанные примеры используют команду CMPSB для сравнения одного байта за одно выполнение. При использовании команды CMPSW для сравнения одного слова необходимо инициализировать регистр СХ значением 5. Кроме того, следует помнить, что команда CMPSW при сравнении слов переставляет байты. Например, сравнивая имена SAMUEL и ARNOLD, команда CMPSW выбирает вместо SA и AR переставленные значения, т.е. AS и RA. В результате вместо "больше" получится "меньше", т.е. неправильный результат. Таким образом, команда CMPSW работает правильно только при сравнении строк, которые содержат числовые данные, определенные как DW, DD или DQ.
SCAS: СКАНИРОВАНИЕ СТРОКИ
Команда SCAS отличается от команды CMPS тем, что сканирует (просматривает) строку на определенное значение байта или слова. Команда SCAS сравнивает содержимое области памяти (адресуемой регистрами ES:DI) с содержимым регистра AL или АХ. В зависимости от значения флага DP команда SCAS также увеличивает или уменьшает адрес в регистре DI на 1 для байта или на 2 для слова. Команда SCAS устанавливает флаги AF, CF, OF, PF, SF и ZF. При использовании префикса REP и значения длины в регистре СХ команда SCAS может сканировать строки любой длины.
Команда SCAS особенно полезна, например, в текстовых редакторах, где, программа должна сканировать строки, выполняя поиск знаков пунктуации: точек, запятых и пробелов.
На рис. 9.1 процедура H10SCAS сканирует область NAME1 на строчную букву m. Так как команда SCASB должна продолжать сканирование до тех пор, пока результат сравнения "не равно" или регистр СХ не равен нулю, то используется префикс REPNE:
REPNE SCASB
Так как область NAME1 содержит слово Assemblers, то команда SCASB находит символ m в пятом сравнении. При использовании отладчика DEBUG для трассировки команд в конце процедуры H10SCAS можно увидеть в регистре АН значение 03 для индикации того, что символ m найден. Команда REP SCASB, кроме того, уменьшит значение регистра СХ от 10 до 06.
Команда SCASW сканирует в памяти слово на соответствие значению в регистре АХ. При использовании команд LODSW или MOV для пересылки слова в регистр АХ следует помнить, что первый байт будет в регистре AL, а второй байт - в регистре АН. Так как команда SCAS сравнивает байты в обратной последовательности, то операция корректна.
СКАНИРОВАНИЕ И ЗАМЕНА
В процессе обработки текстовой информации может возникнуть необходимость замены определенных символов в тексте на другие, например различных редактирующих символов на пробелы. В приведенном ниже фрагменте программы осуществляются сканирование строки STRING и замена символа «амперсанд» (&) -на символ пробела. Когда команда SCASB обнаружит символ & (в примере это будет позиция STRING + 8), то операция сканирования прекратится и регистр DI будет содержать адрес STRING + 9. Для получения адреса символа & необходимо уменьшить содержимое DI на единицу и записать по полученному адресу символ пробела.
STRLEN EQU 15
STRING DB ‘The time&is now’
………..
CLD
MOV AL, ‘&’
MOV CX, STRLEN
LEA DI, STRING
REPNE SCASB
JNZ K20
DEC DI
MOV BYTE PTR[DI] , 20H
K20: RET
При использовании команд MOVSB или MOVSW ассемблер предполагает наличие корректной длины строковых данных и не требует кодирования операндов в команде. Для команды MOVS длина должна быть закодирована в операндах. Например, если поля FLDA н FLDB определены как байтовые (DB), то команда
REP MOVS FLDA, FLDB
предполагает повторяющуюся пересылку байтов из поля FLDB в поле FLDA. Эту команду можно также записать в следующем виде;
REP MOVS ES:BYTE PTR[DI],DS:[SI]
Загрузка регистров DI и SI адресами FLDA и FLDB обязательна в любом случае.
ДУБЛИРОВАНИЕ ОБРАЗЦА
Команда STOS полезна для установки в некоторой области определенных значений байтов и слов. Для дублирования образца, длина которого превышает размер слова, можно использовать команду MOVS с небольшой модификацией. Предположим, что необходимо сформировать строку следующего вида:
***---***---***---***---***--- ...
Вместо того, чтобы определять полностью всю строку, можно определить только первые шесть байтов. Закодируем образец непосредственно перед обрабатываемой строкой следующим образом:
PATTERN DВ ‘***---‘
DISAREA DB 42 DUP(?)
………….
CLD
MOV CX , 21
LEA DI, DISAREA
LEA SI, PATTERN
REP MOVSW
В процессе выполнения команда MOVSW сначала пересылает первое слово (**) из образца PATTERN в первое слово области DISAREA, затем второе слово (*-) и третье {--);
***---***---
│ │
PATTERN DISAREA
К этому моменту регистр DI будет содержать адрес D1SAREA + 6, а регистр SI - PATTERN + 6, который также является адресом DISAREA. Затем команда MOVSW автоматически дублирует образец, пересылая первое слово из DISAREA в DISAREA + 6, из DISAREA+ 2 в DISAREA + 8, из DISAREA ч-4 в DISAREA+10 и т.д. В результате образец будет полностью продублирован по всей области DISAREA:
***---***---***---***---***--- …. ***——
│ │ │ │
PATTERN DISAREA+6 DISAREA+12 DISAREA+42
Данную технику можно использовать для дублирования в области памяти любого образца любой длины. Образец должен быть расположен непосредственно перед принимающей областью.
ПРОГРАММА: ВЫРАВНИВАНИЕ СПРАВА ПРИ ВЫВОДЕ НА ЭКЖРАН
СОМ-программа, изображенная на рис.9.2, иллюстрирует почти весь материал, приведенный в этой главе. Процедуры программы выполняют следующие действия:
B10INPT Принимает имена длиной до 30 символов, вводимых вверху экрана.
D10SCAS Использует команду SCASB для сканирования имен и обхода любого ввода, содержащего символ “звездочка”.
E10RGHT Использует команду MOVSB для выравнивания имен по правой границе, выводит имена в колонку в правой части экрана. Длина в поле ACTNLEN из списка параметров ввода используется для вычисления самого правого символа в имени, например:
JEROME KERN
OSCAR HAMMERSTEIN
RICHARD ROGERS
F10CLNM Использует команду STOSW для очистки области имени в памяти.
ОСНОВНЫЕ ПОЛОЖЕНИЯ НА ПАМЯТЬ
Для цепочечных команд MOVS, STOS, CMPS и SCAS не забывайте инициализировать регистр ES.
Сбрасывайте (CLD) или устанавливайте (STD) флаг направления в соответствии с направлением обработки.
Не забывайте устанавливать в регистрах DI и SI необходимые значения. Например, команда MOVS предполагает операнды DI, SI , а команда CMPS – SI, DI
page 60,132
TITLE EXRINS (СОM) ;Выравнивание справа
CODESG SEGMENT PARA ‘Code’
ASSUME CS:CODESG, DS:CODESG, SS:CODESG, ES:CODESG
ORG 100H
BEGIN: JMP SHORT MAIN
NAMEPAR LABEL BYTE ;Имя списка параметров
MAXNLEN DB 31 ;Максимальная длина
ACTNLEN DB ? ;Число введенных символе
NAMEFLD DB 31 DUP (‘ ‘) ;Имя
PROMPT DB ‘ Name? ‘, ‘$' ‘
NAMEDSP DB 31 DUP (‘ ‘),13,10,’$’
ROW DB 00
MAIN PROC NEAR ;0сновная процедура
MOV AX., 0600H
CALL Q10SCR ;0чистить экран
SUB DX, DX ;Установить курсор в 0
CALL Q20CURS
A10LOOP:
CALL B10INPT ;Ввести имя
TEST ACTNLEN , 0FFH ;Нет имени? (т.е. конец)
JZ A90 ; Да - выйти
CALL D10SCAS ;Найти звездочку
CMP AL, ‘*’ ; Найдена?
JE A10LOOP ; Да - обойти
CALL E10RGHT ; Выровнять имя справа
CALL A10LOOP
A90: RET
MAIN ENDP
; Вывод запроса для ввода имени:
B10INPT PROC
MOV АН, 09
LEA DX, PROMPT ;Выдать текст запроса
INT 21H
RET
B10INPT ENDP
; Поиск звездочки в имени:
D10SCAS PROC
CLD
MOV AL , ' * '
MOV СХ, 30 ;Длина сканирования 30
LEA DI, NAMEFLD
REPNE SCASB
JE D20
MOV AL,20H
D20: RET
D10SCAS ENDP
; Выравнивание и вывод на экран:
E10RGHT PROC
STD
SUB CH, CH
MOV CL, ACTNLEN ;Длина
LEA SI, .NAMEFLD
ADD SI, CX
DEC SI
LEA DI, .NAMEDSP+30
REP MOVSB
MOV DH, ROW
MOV DL, 48
CALL Q20CURS
MOV AH , 09
LEA DX, NAMEDSP
INT 21H
CMP ROW, 20
JAE E20 ; Нет
INC ROW
JMP E90
E20: MOV AX, 0601H
CALL Q10SCR
MOV DH, ROW
MOV DL, 00
CALL Q20CURS
E90: RET
E1ORGHT ENDP
; Очистить область имени
F1OCLNM PROC
CLD
MOV AX, 2020H
MOV CX, 15
LEA DI, NAMEDSP
REP STOSW
RET
F10CLNM ENDP
; Прокрутка экрана:
Q10SCR PROC
MOV ВН, ЗО
MOV СХ, 00
MOV DX, 184FH
INT 10Н
RET
Q10SCR ENDP
; Установить курсор:
Q2QCURS PROC
MOV АН, 02
SUB ВН, ВН
INT 10Н
RET
Q20CURS ENDP
CODESG ENDS
END BEGIN
Рис. 9.2. Выравнивание вправо при выводе на экран
Инициализируйте регистр СХ в соответствии с количеством байтов или слов, участвующих в процессе обработки.
Для обычной обработки используйте префикс REP для команд MOVS и STOS и модифицированный префикс (REPE или REPNE) для команд CMPS и SCAS.
Помните об обратной последовательности байтов в сравниваемых словах при выполнении команд CMPSW и SCASW.
При обработке справа налево устанавливайте начальные адреса на последний байт обрабатываемой области. Если, например, поле NAME1 имеет длину 10 байт, то для побайтовой обработки данных в этой области справа налево начальный адрес, загружаемый командой LEA, должен быть NAME1 + 9. Для обработки слов начальный адрес в этом случае NAME1 +8.
ВОПРОСЫ ДЛЯ САМОПРОВЕРКИ
В данной главе приведены эквивалентные команды для: а) MOVSB, б) LODSB и JSTOSB с префиксом REP. Напишите эквивалентные команды для обработки п словам: а) MOVSW, б) LODSW и в) STOSW с префиксом REP.
Введите, ассемблируйте и выполните компоновку программы, приведенной на рис.9.1. Не забудьте об инициализации регистра ES. Замените команды MOVSB и MOVSW для пересылки справа налево. Измените процедуру H10SCAS для сканирования поля NAME1 на слово mb. Используйте отладчик DEBUG для трассировки процедур и обратите внимание на содержимое сегмента данных и регистров.
Имеются следующие определения:
DATASG SEGMENT PARA
CONAME DB 'SPACE EXPLORERS INC. '
PRLINE DB 20 DUP (‘ ‘)
Используя цепочечные команды, выполните:
а) пересылку данных из CONAME в PRLINE слева направо;
б) пересылку данных из CONAME в PRLINE справа налево;
в) загрузку третьего и четвертого байтов области CONAME в регистр АХ;
г) сохранение содержимого регистра АХ в область по адресу PRLINE + 5;
д) сравнение данных в областях CONAME и PRLINE (они должны быть не равны);
е) сканирование области CONAME и поиск в ней символа «пробел». Если символ будет найден, то переслать его в регистр ВН.
10. Арифметические операции I: Обработка двоичных данных
Цель: дать сведения об операциях сложения, вычитания, умножения и деления двоичных данных.
Несмотря на то, что мы привыкли к десятичной арифметике (основание 10), компьютер работает только с двоичной арифметикой (основание 2). Кроме того, ввиду ограничения, накладываемого 16-битовыми регистрами, большие величины требуют специальной обработки.
В данной главе даются сведения об операциях сложения, вычитания, умножения и деления для беззнаковых и знаковых данных. В главе также приводится много примеров и предупреждений о различных ловушках для опрометчивых исследователей мира микропроцессора.
СЛОЖЕНИЕ И ВЫЧИТАНИЕ
Команды ADD и SUB выполняют сложение и вычитание байтов или
слов, содержащих двоичные данные. Вычитание осуществляется в
компьютере по методу сложения с двоичным дополнением: для
второго операнда устанавливаются обратные значения битов и
прибавляется 1, а затем происходит сложение с первым
операндом. Во всем, кроме первого шага, операции сложения и
вычитания идентичны.
На рис.10.1 представлены примеры команд ADD и SUB,
обрабатывающих байты или слова. В процедуре В10ADD
используется команда ADD для сложения байтов, а в процедуре
С10SUB команда SUB вычитает слова. Примеры показывают все
пять возможных ситуаций:
сложение/вычитание регистр - регистр;
сложение/вычитание память - регистр;