Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
лекции / СПО2.doc
Скачиваний:
114
Добавлен:
11.02.2014
Размер:
527.87 Кб
Скачать

30. Команды обработки строковых данных в ассемблере.

Символьные строки

Символьная строка используется для описания данных, таких как, например, имена людей или заголовки страниц. Содержимое строки отмечается одиночными кавычками, например ‘PC’, или двойными кавычками – “PC”. Ассемблер переводит символьные строки в объектный код в обычном формате ASCII.

Символьная строка определяется только директивой DB, в которой указывается более двух символов в нормальной последовательности слева направо. Директива DB представляет единственно возможный формат для определения символьных данных

0000 FL1 DB ? ;Не инециализировано

0001 50 65 72 73 6F 6E FL2 DB ‘Personal Computer’ ;Символьная строка

61 6C 20 43 6F 6D

70 75 74 65 72

Команды обработки строк

Часто бывает необходимо переслать или сравнить поля данных, которые превышают по длине одно слово. Например, необходимо сравнить описания или имена для того, чтобы отсортировать их в восходящей последовательности. Элементы такого формата известны как строковые данные и могут являться как символьными, так и числовыми. Для обработки строковых данных ассемблер имеет пять команд обработки строк: MOVS, LODS, STOS, CMPS, SCAS.

Ниже перечислены регистры, участвующие в цепочных командах ( для однобайтовых и двухбайтовых вариантов). Предположим, что регистры DI и SI содержат необходимые адреса:

Команда Операнды Байт Слово

MOVS DI, SI MOVSB MOVSW

LODS AL, SI или AX, SI LODSB LODSW

STOS DI, AL или DI, AX STOSB STOSW

CMPS SI, DI CMPSB CMPSW

SCAS DI, AL или DI, AX SCASB SCASW

Операнды указываются, например, для команды MOVS, но опускаются для MOVSB и MOVSW. Эти команды предполагают, что регистры DI и SI содержат относительные адреса, указывающие на необходимые области памяти ( для загрузки можно использовать команду LEA). Регистр SI обычно связан с регистром сегмента данных – DS:SI. Регистр DI всегда связан с регистром дополнительного сегмента – ES:DI. Следовательно, для рассматриваемых команд требуется инициализация регистра ES ( обычно адресом в регистре DS).

Команда REP. Префикс повторения команды, обеспечивает повторение команды несколько раз. Префикс REP кодируется непосредственно перед цепочной командой. Для использования префикса REP необходимо установить начальное значение в регистре СХ. При выполнении цепочной команды с префиксом REP происходит уменьшение на 1 значения в регистре СХ до нуля. Таким образом, можно обрабатывать строки любой длины.

Флаг направления определяет направление повторяющейся операции:

? для направления слева направо необходимо с помощью команды CLD установить флаг DF в0;

? для направления справа налево необходимо с помощью команды STD установить флаг DF в1.

В следующем примере выполняется пересылка 20 байт из STR1 в STR2. Предположим, что оба регистра DS и ES инициализированы адресом сегмента данных:

STR1 DB 20 DUP (‘*’)

STR2 DB 20 DUP (‘ ‘)

………………………………

CLD ; Сброс флага DF

MOV CX, 20 ; Счётчик на 20 байт

LEA DI, STR2 ; Адрес “куда”

LEA SI, STR1 ; Адрес “откуда”

REP MOVSB ; Переслать данные

При выполнении команд CMPS и SCAS возможна установка флагов состояния, чтобы операция могла прекратиться после обнаружения необходимого условия. Ниже приведены модификации префикса REP для этих целей:

REP - повторять операцию до тех пор, пока СХ не равно 0;

REPZ - повторять операцию до тех пор, пока флаг ZF показывает

или “равно или ноль”. Прекратить операцию при флаге ZF,

REPE указывающем на не равно или не ноль, или при СХ равном 0.

REPNE - повторять операцию до тех пор, пока флаг ZF показывает

или “не равно или не ноль”. Прекратить операцию при флаге ZF

REPNZ указывающем на равно или ноль, или при СХ равном 0.

Команда MOVS. Пересылка одного байта или одного слова из одной области памяти в другую. Команда MOVS с префиксом REP и счётчиком в регистре CX может выполнять пересылку любого числа символов более эффективно.

Для области , принимающей строку, сегментным регистром является регистр ES, а регистр DI содержит относительный адрес. Для области, передающей строку, сегментным регистром является регистр DS, а регистр SI содержит относительный адрес. Таким образом, в начале программы перед выполнением команды MOVS необходимо инициализировать регистр ES вместе с регистром DS, а также загрузить относительные адреса полей в регистры DI и SI. В зависимости от состояния флага DF команда MOVS производит увеличение или уменьшение на 1 (для байта) или на 2 (для слова) содержимого регистров DI и SI.

Ниже приведены команды, эквивалентные цепочной команде REP MOVSB:

LASD1: MOV AL, [SI]

MOV [DI], AL

INC/DEC DI ; Инкремент или декремент

INC/DEC SI ; Инкремент или декремент

LOOP LASD1

В рассматриваемых далее процедурах и примерах предполагается, что регистры инициализированы директивой, а данные определены следующим образом:

NAM1 DB ‘Assemblers’

NAM2 DB 10 DUP (‘ ‘)

Процедура С10М использует команду MOVSВ для пересылки содержимого десятибайтового поля NAM1 в поле NAM2. Первая команда CLD сбрасывает флаг направления в 0 для обеспечения процесса пересылки слева направо. В нормальном состоянии флаг DF обычно имеет нулевое значение и команда CLD используется из предосторожности. Две команды LEA загружают регистры SI и DI относительными адресами NAM1 и NAM2 соответственно. Команда MOV заносит в регистр CX значение 10 -– длину полей NAM1 и NAM2. Команда REP MOVSB выполняет следующее:

? пересылает самый левый байт из поля NAM1(адресованного регистрами ES:DI ) в самый левый байт поля NAM2(адресованного регистрами DS:SI);

? увеличивает на 1 адреса в регистрах DI и SI для следующего байта;

? уменьшает СХ на 1;

? повторяет перечисленные действия (в данном случае 10 раз), пока содержимое регистра СХ не станет равным нулю.

C10M PROC NEAR

CLD

LEA SI, NAM1

LEA DI, NAM2

MOV CX, 10 ; Пересылка 10 байтов

REP MOVSB ; из NAM1 в NAM2

RET

C10M ENDP

Поскольку флаг DF имеет нулевое значение, команда MOVSB увеличивает адреса в регистрах DI и SI, в каждой итерации процесс перемещается на байт вправо, т.е. пересылает байт из NAM1 в NAM2 и т.д. Если бы флаг DF был равен 1, тогда команда MOVSB уменьшала бы адреса в регистрах DI и SI, ваполняя процесс справа налево. Но в этом случае регистры SI и DI необходимо инициализировать адресами последних байтов полей, т.е. NAM1+9 и NAM2+9 соответственно.

Команда LODS. Загружает из памяти один байт в регистр AL или одно слово в регистр AX. Адрес памяти определяется регистрами DS:SI. В зависимости от значения флага DF происходит увеличение или уменьшение значения в регистре SI.

Поскольку одна команда LODSзагружает регистр, то практической пользы от префиксаREPв данном случае нет. Часто простая командаMOVполностью адекватна командеLODS, хотя генерирует 3 байт машинного кода, аLODS– только один, но требует инициализации регистраSI. Можно использовать командуLODSв случае, когда требуется продвигаться вдоль строки ( по байту или по слову), проверяя загружаемый регистр на конкретное значение.

Команды, эквивалентные команде LODSB:

MOV AL, [SI]

INC SI

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

Практическая польза команды STOS с префиксом REP – инициализация области данных конкретным значением, например очистка дисплейного буфера пробелами. Длина области ( в байтах или в словах) загружается в регистр СХ. Команды, эквивалентные команде REP STOS:

LASD1: MOV [DI], AL

INC/DEC DI

LOOP LASD1

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

Рассмотрим процесс сравнения двух строк, содержащих имена JEAN и JOAN. Сравнение побайтово слева направо приводит к следующему:

J : J Равно

E : O Не равно (E меньше O)

A : A Равно

N : N Равно

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

REPE CMPSB

В процедуре G10 происходит сравнение содержимого полей NAM1 и NAM2. Так как ранее команда MOVSB переслала содержимое поля NAM1 в поле NAM2, то команда CMPSB продолжается по всем десяти байтам и завершается состоянием “равно/нуль”: флаг SF получает значение 0 (положительно) и флаг ZF – 1 (нуль). Процедура заканчивается с результатом “равно/нуль” и заносит 01 в регистр BH для индикации результата сравнения.

G10 PROC NEAR

CLD

MOV CX, 10

LEA SI, NAM1

LEA DX, NAM2

REPE CMPSB ; Срвн.NAM1 и NAM2

JNE G11 ; Не равны ?

MOV BH, 01

G11: RET

G10 ENDP

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

Процедура G20 сканирует областьNAM1на строчную буквуm. Так как командаSCASBдолжна продолжать сканирование до тех пор, пока результат сравнения “не равно” или регистр СХ не равен нулю, то используется префиксREPNE:

REPNESCASB

Так как область NAM1 содержит слово Assemblers, то команда SCASB находит символ m в пятом сравнении. В конце процедуры в регистр AH записывается значение 03 для индикации того, что символ m найден.

G20 PROC NEAR

CLD

MOV CX, 10

LEA DI, NAM1

MOV AL, ‘m’ ; Поик символа ‘m’

REPNE SCASB ; в NAM1

JNE H20 ; Если нет - выйти

MOV AH, 03

H20: RET

G10 ENDP

Существуют различные причины для преобразований между строчными и заглавными буквами. Например, вы могли получить файл данных, созданный на компьютере, который работает только с заглавными буквами. Или некая программа должна позволить пользователям вводить команды как заглавными, так и строчными буквами (например, YES или yes) и преобразовать их в заглавные для проверки.

Заглавные буквы от A до Z имеют шест.коды от 41 до 5A, а строчные буквы от a до z имеют шест.коды от 61 до 7A. Единственная pазница в том, что пятый бит равен 0 для заглавных букв и 1 для строчных:

Биты : 7 6 5 4 3 2 1 0 Биты: 7 6 5 4 3 2 1 0

Буква A: 0 1 0 0 0 0 0 1 Буква a: 0 1 1 0 0 0 0 1

Буква Z: 0 1 0 1 1 0 1 0 Буква z: 0 1 1 1 1 0 1 0

COM-программа, приведенная ниже преобразует данные в поле TITLEX из строчных букв в прописные, начиная с адреса TITLEX. Программа инициализирует регистр BX адресом TITLEX и использует его для пересылки символов в регистр AH, начиная с TITLEX. Если полученное значение лежит в пределах от шест.61 и до 7A, то команда AND устанавливает бит 5 в 0:

AND AH,11011111B

Все символы, отличные от строчных букв (от a до z), не изменяются. Измененные символы засылаются обратно в область ТITLEX, значение в регистре BX увеличивается для очередного символа и осуществляется переход на следующий цикл.

Используемый таким образом регистр BX действует как индексный регистр для адресации в памяти. Для этих целей можно использовать также регистры SI и DI.

TITLE CASE (COM) ; Перекодировка в заглавные буквы

0000 CODESG SEGMENT PARA 'CODE'

ASSUME CS:CODESG,DS:CODESG,SS:CODESG

0001 ORG 100H

0001 EB 1C 90 BEGIN: JMP MAIN

0003 43 68 61 6E 67 65 TITLEX DB 'Change to uppercase letters'

20 74 6F 20 75 70

70 65 72 63 61 73

65 20 6C 65 74 74

65 72 73

011E MAIN PROC NEAR

011E 8D 1E 0104 R LEA BX,TITLEX ;Адрес первого символа

0122 B9 001F MOV CX,31 ;Число символов

0125 B20:

0125 8A 27 MOV AH,[BX] ;Символ из TITLEX

0127 80 FC 61 CMP AH,61H ;Это

012A 72 0A JB B30 ;прописная

012C 80 FC 7A CMP AH,7AH ;буква

012F 77 05 JA B30 ; ?

0131 80 E4 DF AND AH,11011111B;Да - преобразовать

0134 88 27 MOV [BX],AH ;Записать в TITLEX

0136 B30:

0136 43 INC BX ;Следующий символ

0137 E2 EC LOOP B20 ;Повторить цикл 31 раз

0139 C3 RET

013A MAIN ENDP

013A CODESG ENDS

END BEGIN

Соседние файлы в папке лекции