Сист. прогр. Ч2 (1085771)
Текст из файла
133
9. Команды обработки строк
Цель: объяснить назначение специальных цепочечных команд, используемых для обработки символьных данных.
ВВЕДЕНИЕ
Команды, показанные в предыдущих главах, оперировали одним байтом или одним словом за одно выполнение. Часто, однако, бывает необходимо переслать или сравнить поля данных, которые превышают по длине одно слово. Например, необходимо сравнить описания или имена для того, чтобы отсортировать их в восходящей последовательности. Элементы такого формата известны как строковые данные и могут являться как символьными, так и числовыми. Для обработки строковых данных ассемблер имеет пять команд обработки строк:
MOVS переслать один байт или одно слово из одной области памяти в другую;
LODS загрузить из памяти один байт в регистр AL или одно слово в регистр АХ;
STOS записать содержимое регистра AL или АХ в память;
CMPS сравнить содержимое двух областей памяти размером в
один байт или в одно слово;
SCAS сравнить содержимое регистра AL или АХ с содержимым памяти.
Префикс REP позволяет этим командам обрабатывать строки любой длины.
ОСОБЕННОСТИ КОМАНД ОБРАБОТКИ СТРОК
Цепочечная команда может быть закодирована для повторяющейся обработки одного байта или одного слова за одно выполнение. Например, можно выбрать "однобайтовую" команду для обработки строки с нечетным числом байтов или "двухбайтовую" команду для обработки четного числа байтов. Ниже перечислены регистры, участвующие в цепочечных командах (для однобайтовых и двухбайтовых вариантов). Предположим, что регистры DI и SI содержат необходимые адреса:
Команда Операнды Байт Слово
MOVS DI, SI MOVSB MOVSW
LODS AL,SI или АХ,SI LODSB LODSW
STOS DI, AL или DI,AX STOSB STOSW
CMPS SI, DI CMPSB CMPSW
SCAS DI, AL или DI ,АХ SCASB SCACW
Операнды указываются, например, для команды MOVS, но опускаются для MOVSB и MOVSW. Эти команды предполагают, что регистры DI и SI содержат относительные адреса, указывающие на необходимые области памяти (для загрузки можно использовать команду LEA). Регистр SI обычно связан с регистром сегмента данных - DS:SI. Регистр DI всегда связан с регистром дополнительного сегмента - ES:DI. Следовательно, команды MOVS, STOS, CMPS и SCAS требуют инициализации регистра ES (обычно адресом в регистре DS).
REP: ПРЕФИКС ПОВТОРЕНИЯ КОМАНДЫ
Несмотря на то, что цепочечные команды имеют отношение к одному байту или одному слову, префикс REP обеспечивает повторение команды несколько раз. Префикс кодируется непосредственно перёд цепочечной командой, например REP MOVSB. Для использования префикса REP необходимо установить начальное значение в регистре СХ. При выполнении цепочечной команды с префиксом REP происходит уменьшение на 1 значения в регистре СХ до нуля. Таким образом, можно обрабатывать строки любой длины.
Флаг направления определяет, направление повторяющейся
операции:
-
для направления слева направо необходимо с помощью
команды CLD установить флаг DF в 0;
-
для направления справа налево необходимо с помощью
команды STD установить флаг DF в 1.
В следующем примере выполняется пересылка 20 байт из STRING1 в STRING2. Предположим, что оба регистра DS и ES инициализированы адресом сегмента данных:
STRING1 DB 20 DUP(‘*’)
STRING2 DB 20 DUP (‘ ‘)
……………….
CLD ;Сброс флага DF
MOV CX, 20 ;Счетчик на 20 байт
LEA DI, STRING2. ;Адрес "куда"
LEA SI, STRING1. ;Адрес "откуда"
REP MOVSB ;Переслать данные
При выполнении команд CMPS и SCAS возможна установка флагов состояния, так чтобы операция могла прекратиться сразу после обнаружения необходимого условия. Ниже приведены модификации префикса REP для этих целей:
REP повторять операцию до тех пор, пока СХ не равно 0;
REPZ повторять операцию до тех пор, пока флаг ZF показывает или "равно или ноль". Прекратить операцию при флаге ZF,
RЕРЕ указывающем на не равно или не ноль, или при СХ, равном 0;
REPNE повторять операцию до тех пор, пока флаг ZF показывает или "не равно или не ноль". Прекратить операцию при флаге
REPNZ ZF, указывающем на " равно или ноль", или при СХ, равном 0.
Для процессоров 8086, 80286 и 80386, обрабатывающих слово за одно выполнение, использование цепочечных команд, где это возможно, приводит к повышению эффективности работы программы.
MOVS: ПЕРЕСЫЛКА СТРОКИ
На рис. 7.5. была показана программа для пересылки девятибайтового поля. Программа включала три команды для инициализации и пять команд для цикла. Команда MOVS с префиксом REP и счетчиком в регистре СХ может выполнять пересылку любого числа символов более эффективно.
Для области, принимающей строку, сегментным регистром является регистр ES, а регистр DI содержит относительный адрес. Для области, передающей строку, сегментным регистром является регистр DS, а регистр SI содержит относительный адрес. Таким образом, в начале программы перед выполнением команды MOVS необходимо инициализировать регистр ES вместе с регистром DS, a также загрузить требуемые относительные адреса полей в регистры DI и SI. В зависимости от состояния флага DF команда MOVS производит увеличение или уменьшение на 1 (для байта) или на 2 (для слова) содержимого регистров DI и S1,
Приведем команды, эквивалентные цепочечной команде REP MOVSB:
JCXZ LABEL2
IABEL1: MOV, AL,[SI]
MOV [DI],AL
INC/DEC DI ;Инкремент или декремент
INC/DEC SI ;Инкремент или декремент
LOOP LABEL1
LABEL2: ...
В программе на рис. 9.1 процедура C10MVSB использует команду MOVSB для пересылки содержимого десятибайтового поля NAME1 в поле NAME2. Первая команда CLD сбрасывает флаг направления в 0 для обеспечения процесса пересылки слева направо. В нормальном состоянии флаг DF обычно имеет нулевое значение и команда CLD используется из предосторожности.
Две команды LEA загружают регистры SI и DI относительными адресами NAME1 и NAME2 соответственно. Так как регистры DS и ES были ранее инициализированы адресом DATASG, то полные адреса полей NAME1 и NAME2 будут в регистрах ES:DI и DS:SI. (СОМ-программа автоматически инициализирует регистры ES и DS). Команда MOV заносит в регистр СХ значение 10 - длину полей NAME1 и NAME 2. Команда REP MOVSB выполняет следующее:
-
пересылает самый левый байт из поля NAME1 (адресованного регистрами ES:DI) в самый левый байт поля NAME2 (адресованного регистрами DS:SI);
-
увеличивает на 1 адреса в регистрах DI и SI для следующего байта;
-
уменьшает СХ на 1;
-
повторяет перечисленные действия (в данном случае 10 раз), пока содержимое регистра СХ не станет равным нулю.
Поскольку флаг DF имеет нулевое значение, команда MOVSB увеличивает адреса в регистрах DI и SI, и в каждой итерации процесс перемещается на байт вправо, т.е. пересылает байт из NAME1 + 1 в NAME2 + 1 и т.д. Если бы флаг DF был равен 1, тогда команда MOVSB уменьшала бы адреса в регистрах DI и SI, выполняя процесс справа налево. Но в этом случае регистры SI и DI необходимо инициализировать адресами последних байтов полей, т.е. NAME1+9 и NAME2 + 9 соответственно.
В процедуре D10MVSW (рис. 9.1) используется команда MOVSW, пересылающая одно слово за одно выполнение. Так как команда MOVSW увеличивает адреса в регистрах DS и SI на 2, операция требует только пять циклов. Для процесса пересылки справа налево регистр SI должен быть инициализирован адресом NAME1 +8, а регистр DI - NAME2 + 8.
LODS: ЗАГРУЗКА СТРОКИ
Команда LODS загружает из памяти в регистр AL один байт или в регистр АХ одно слово. Адрес памяти определяется регистрами DS:SI. В зависимости от значения флага DF происходит увеличение или уменьшение значения в регистре SI.
Поскольку одна команда LODS загружает регистр, то практической пользы от префикса REP в данном случае нет. Часто простая команда MOV полностью адекватна команде LODS, хотя MOV генерирует 3 байта машинного кода, a LODS - только один, но требует инициализации регистра SI. Можно использовать команду LODS в случае, когда требуется продвигаться вдоль строки (по байту или по слову), проверяя загружаемый регистр на конкретное значение.
Команды, эквивалентные команде LODSB:
MOV AL,[SI]
INC SI
Ha рис.9.1 процедура E10LODS демонстрирует использование команды LODSW. В примере обрабатывается только одно слово: первый байт из области NAME1 (содержащий значение As) заносится в регистр AL, а второй байт - в регистр АН. В результате в регистре АХ получится значение sA.
STOS: ЗАПИСЬ СТРОКИ
Команда STOS записывает (сохраняет) содержимое регистра AL или АХ в байте или в слове памяти. Адрес памяти всегда представляется регистрами ES:DI. В зависимости от флага DF команда STOS также увеличивает или уменьшает адрес в регистре DI на 1 для байта или на 2 для слова.
Практическая польза команды STOS с префиксом REP -инициализация области данных конкретным значением, например очистка дисплейного буфера пробелами. Длина области (в байтах или в словах) загружается в регистр СХ. Команды, эквивалентные команде REP STOSB:
JCXZ LABEL2
LABEL1: MOV [DI], AL
INC/DEC DI ;Инкремент или декремент
LOOP LABEL1
LABEL2: ...
На рис.9.1 процедура F10STOS демонстрирует использование команды STOSW. Операция осуществляет запись пробелов (2020) пять раз в область NAME3, причем значение из регистра AL заносится в первый байт, а из регистра АН - во второй. По завершении команды регистр DI содержит адрес NAME3+10.
CMPS: СРАВНЕНИЕ СТРОК
Команда CMPS сравнивает содержимое одной области памяти (адресуемой регистрами DS:SI) с содержимым другой области (адресуемой регистрами ES:DI). В зависимости от флага DF команда CMPS также увеличивает или уменьшает адреса в регистрах SI и DI на 1 для байта или на 2 для слова. Команда CMPS устанавливает флаги AF, CF, OF, PF, SF и ZF. При использовании префикса REP в регистре СХ должно находиться значение длины сравниваемых полей. Команда CMPS может сравнивать любое число байтов или слов.
Рассмотрим процесс сравнения двух строк, содержащих имена JEAN и JOAN. Сравнение побайтово слева направо приводит к следующему:
J : J Равно
Е : О Не равно (Е меньше О)
А : А Равно
N : N Равно
page 60,132
TITLE STRING (EXE) ;Строковые операции
STACKSG SEGMENT PARA STACK ‘Stack’
DW 32 DUP(?)
STACKSG 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 E10L0DS ;Подпрограмма LODS
CALL F10STOS ;Подпрограмма CMPS
CALL H10SCAS ;Подпрограмма SCAS
RET
BEGIN ENDP
Использование MOVSB:
C10MVSB PROC NEAR
CLD
LEA SI, NAME1
LEA DI, NAME2
MOV CX,10
REP MOVSB
RET
C10MVSB ENDP ;Переслать 10 байтов из NAME1 в NAME2
; Использование MOVSW:
D10MVSW PROC NEAR
CLD
LEA SI, NAME2
LEA DI, NAME3
MOV CX, 05
REP MOVSW
RET
D10MVSW ENDP ;Переслать 5 слов из NAME2 в NAME3
; Использование LODSW:
E10LODS PROC NEAR
CLD
LEA SI, NAME1 ;3агрузить 1-е слово
LODSW ; из NAME1 в АХ
RET
E10LODS ENDP
; Использование STOSW:
F10STOS PROC NEAR
CLD
LEA DI, NAME3
MOV СХ, 05
MOV AX, 2020H ;Переслать пробелы
REP STOSW ; в NAME3
RET
F10STOS ENDP
G10CMPS PROC NEAR
CLD
MOV CX, 10
LEA SI, NAME1
LEA DI, NAME2
REPE CMPSB ;Сравн. NAME1 и NAME2 He равны?
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 СХ, 10
LEA DI , NAME1
MOV AL, ‘m’ ;Поиск символа 'm1
REPNE SCASB ; в NAME1
JNE H20 ;Если нет - выйти
MOV АН,03
H20: RET
H10SCAS ENDP
CODESG ENDS
END BEGIN
Рис. 9.1.
Сравнение всех четырех байтов заканчивается сравнением N:N -равно/нуль. Так как имена "не равны", операция должна прекратиться, как только будет обнаружено условие "не равно". Для этих целей команда REP имеет модификацию REPE, которая повторяет сравнение до тех пор, пока сравниваемые элементы равны или регистр СХ не равен нулю. Кодируется повторяющееся однобайтовое сравнение следующим образом:
REPE CMPSB
Характеристики
Тип файла документ
Документы такого типа открываются такими программами, как Microsoft Office Word на компьютерах Windows, Apple Pages на компьютерах Mac, Open Office - бесплатная альтернатива на различных платформах, в том числе Linux. Наиболее простым и современным решением будут Google документы, так как открываются онлайн без скачивания прямо в браузере на любой платформе. Существуют российские качественные аналоги, например от Яндекса.
Будьте внимательны на мобильных устройствах, так как там используются упрощённый функционал даже в официальном приложении от Microsoft, поэтому для просмотра скачивайте PDF-версию. А если нужно редактировать файл, то используйте оригинальный файл.
Файлы такого типа обычно разбиты на страницы, а текст может быть форматированным (жирный, курсив, выбор шрифта, таблицы и т.п.), а также в него можно добавлять изображения. Формат идеально подходит для рефератов, докладов и РПЗ курсовых проектов, которые необходимо распечатать. Кстати перед печатью также сохраняйте файл в PDF, так как принтер может начудить со шрифтами.