Title prg_10_3. Dseg segment PARA public ‘data’. Mas DB 1,0,9,8,0,7,8,0,2,0 ; это заданный одномерный массив байт
TITLE prg_10_3 STACK SEGMENT PARA STACK ‘STACK’ DB 64 DUP(‘STACK’); Область стека STACK ENDS DSEG SEGMENT PARA PUBLIC ‘DATA’ Mas db 1, 0, 9, 8, 0, 7, 8, 0, 2, 0; это заданный одномерный массив байт Len_mas equ 10; количество элементов в массиве DSEG ENDS CSEG SEGMENT PARA PUBLIC ‘CODE’ ASSUME CS: CSEG, DS: DSEG, SS: STACK START: PUSH DS SUB AX, AX PUSH AX MOV AX, DSEG ; инициировать адрес сегмента данных MOV DS, AX MOV СX, LEN_MAS; в сх – счетчик элементов массива XOR AX, AX XOR SI, SI JCXZ EXIT; проверка сх на 0, если 0, то выход CYC1: CMP MAS[SI], 0; сравнить очередной элемент задан. массива с 0 JNE M1; если не равно 0, то на m1 INC AL; увеличение счетчика нулевых элементов M1: INC SI; перейти к следующему элементу LOOP CYC1 EXIT: MOV AX, 4C00H INT 21H; возврат управления операционной системе END START TITLE prg_10_4 STACK SEGMENT PARA STACK ‘STACK’ DB 64 DUP(‘STACK’); Область стека STACK ENDS DSEG SEGMENT PARA PUBLIC ‘DATA’ Mas db 1, 0, 9, 8, 0, 7, 8, 0, 2, 0; это заданный одномерный массив байт Len_mas equ 10; количество элементов в массиве MESS1 DB ‘в массиве нет нулевых элементов, $’ MESS2 DB ‘найден первый нулевой элемент в позиции, $’ DSEG ENDS CSEG SEGMENT PARA PUBLIC ‘CODE’ ASSUME CS: CSEG, DS: DSEG, SS: STACK START: PUSH DS
SUB AX, AX PUSH AX MOV AX, DSEG ; инициировать адрес сегмента данных MOV DS, AX MOV СX, LEN_MAS; в сх – счетчик элементов массива XOR AX, AX XOR SI, SI JCXZ EXIT; проверка сх на 0, если 0, то выход MOV SI, -1; готовим SI к адресации элементов MAS CYC1: INC SI CMP MAS[SI], 0; сравнить очередной элемент задан. массива с 0 LOOPNZ CYC1; цикл перебора элементов массива JZ EXIT; на эту команду попадем, если весь массив просмотрен и нулевой элемент не обнаружен, либо, если нулевой элемент найден . . . . . здесь поместить команды выдачи сообщения MESS1 INC SI; определить номер первого нулевого элемента EXIT: . . . . . . здесь поместить команды выдачи сообщения MESS2 и номера первого нулевого элемента MOV AX, 4C00H INT 21H; возврат управления операционной системе END START TITLE prg_10_5 STACK SEGMENT PARA STACK ‘STACK’ DB 64 DUP(‘STACK’); Область стека STACK ENDS DSEG SEGMENT PARA PUBLIC ‘DATA’ Mas db 1, 0, 9, 8, 0, 7, 8, 0, 2, 0; это заданный двумерный массив байт db 1, 0, 9, 8, 6, 7, 8, 0, 5. 4 db 0, 1, 9, 8, 0, 7, 8, 0, 2, 0 db 1, 2, 9, 8, 0, 7, 8, 0, 2, 3 db 10, 0, 0, 9, 8, 0, 0, 8, 0, 2 Len_mas equ 10; количество элементов в строке DSEG ENDS CSEG SEGMENT PARA PUBLIC ‘CODE’ ASSUME CS: CSEG, DS: DSEG, SS: STACK START: PUSH DS SUB AX, AX PUSH AX MOV AX, DSEG ; инициировать адрес сегмента данных MOV DS, AX XOR AX, AX MOV CX, 5; в счетчик – число строк массива
LEA BX, MAS; смещение начала массива занести в ВХ CYC1: PUSH CX; сохранить в стеке текущее значение счетчика строк XOR SI, SI; начать обработку очередной строки MOV СX, LEN_MAS; в сх – счетчик элементов строки CYC2: CMP BYTE PTR [BX+SI], 0; очередной элемент 0? JNE NO-ZERO; если не 0, перейти на метку MOV BYTE PTR [BX+SI], 0FFH; заменить нулевой элемент заданным значением NO_ZERO: INC SI; перейти к следующему элементу строки LOOP CYC2 POP CX; восстановить счетчик внешнего цикла (номера строки) ADD BX, LEN_MAS; перейти к следующей строке LOOP CYC1 EXIT: MOV AX, 4C00H INT 21H; возврат управления операционной системе END START
Тема 2. 6 Команды обработки строк 1. Общие сведения 2. Префиксы повторения 3. Пересылка 4. Сравнение 5. Сканирование 6. Загрузка 7. Сохранение Эти команды позволяют производить действия над блоками байтов или слов памяти объемом до 64 Кбайт, которые трактуются как строки двоичных кодов. Фактически двоичные строки могут быть числовыми значениями или символьными значениями, для команд это безразлично. Рассматриваемые в этом параграфе команды приведены в таблице:
Обращает на себя внимание тот факт, что группы команд одинакового действия насчитывают по 3 команды, у которых изменяется только последняя буква мнемокода. Объясняется это тем, что фактически процессор выполняет только команды без операндов, на которые транслятор замещает команды с операндами. Эти команды с операндами нужны транслятору только для тех целей, чтобы определить, будут в операциях участвовать байты (команды имеют конечным символом мнемокода символ В) или слова (команды имеют конечным символом мнемокода символ W). В командах обработки строк по умолчанию предполагается, что строка_приемник находится в дополнительном сегменте данных, а строка_источник – в основном. Процессор адресует строку_приемник через регистр DI, а строку_ источник – через регистр SI. Все команды являются групповыми, поэтому автоматически модифицируют указатели в регистрах DI и SI для адресации следующего элемента обрабатываемых строк. В операциях для адресации следующего элемента обрабатываемых строк. В операциях “участвует” флаг направления DF, значение которого определяет, будут ли значения регистров DI и SI увеличиваться или уменьшаться при выполнении групповой команды. Если флаг DF равен 0, то значения регистров DI и SI увеличиваются ( что равносильно выполнению команды INC), в противном случае значения регистров DI и SI уменьшаются (что равносильно выполнению команды DEC после обработки очередного символа). Флаг направления может быть установлен в 0 командой CLD или установлен в 1 командой STD. И, наконец, чтобы одной командой можно было обрабатывать группу последовательных элементов памяти, перед командой указывается префикс повторения.
2. Как видно из таблицы, в Ассемблере существуют 3 вида префиксов повторения. Количество повторений извлекается из регистра_счетчика CX, также как и при организации циклов. Так, команды CLD MOV CX, 500 REP MOVS DEST, SOURCE приведут к пересылке 500 байтов или слов (это зависит от описания переменных DEST и SOURCE) из области памяти SOURCE в область памяти DEST. Аналогично командам цикла при каждом повторении групповой команды с префиксом значение счетчика повторений уменьшается на 1. Префикс REPE / REPZ используется, если групповую команду необходимо прервать, когда сбрасывается в 0 флаг ZF. Следовательно, применять этот префикс нужно к командам, воздействующим на флаг ZF, например, к команде сравнения строк CMPS: CLD MOV CX, 100 REP E CMPS DEST, SOURCE Эта группа команд сравнивает строки DEST и SOURCE до тех пор, пока элементы в сравниваемых строках совпадают или пока не просмотрены все 100 элементов сравниваемых строк (или иначе действие этих команд можно определить как поиск первого несовпадения строк). Действие префикса REPNE / REPNZ противоположно действию REPE / REPZ. Так, команды
CLD MOV CX, 100 REP NE CMPS DEST, SOURCE Сравнивают строки до первого совпадения или до конца строки, если совпадение в соответствующих позициях строк не будет обнаружено. Механизм действия групповых команд MOVS и CMPS понятен из приведенных примеров, причем MOVS не отличатся по действию от MOV, а вот CMPS в отличие от CMP вычитает операнд_приемник из операнда_источника, что необходимо учитывать при выборе команды условного перехода после сравнения (используйте для выбора следующую таблицу).
Особенностью групповых команд является то, что при использовании префиксов REPE / REPZ или REPNE / REPNZ неизвестно, было обнаружено совпадение или несовпадение или нет (просмотрены все элементы строки). Выяснить имевшую место ситуацию можно, используя команды проверки флага ZF, например, следующим образом: CLD MOV CX, 100 REP NE CMPS DEST, SOURCE ; найти совпадение элементов строк JNE NOT_FOUND; совпадение обнаружено? . . . . . . . . ; да. Продолжим обработку этими . . . . . . . . ; командами NOT_FOUND: . . . . ; нет. Обрабатываем вариант . . . . . . . ; отсутствия совпадения Вопрос: Какая команда должна быть выполнена перед меткой NOT_FOUND? Остановимся еще на одной особенности команд обработки строк, которую мы до настоящего времени “замели под ковер”. Она связана с использованием дополнительного сегмента для размещения строки_приемника. Во-первых, описание этого сегмента отличается от основного сегмента данных только именем, но при его наличии нельзя забывать о назначении регистра ES: DSEG SEGMENT PARA PUBLIC ‘DATA’ SOURCE DW 1, 2, 3, 4, 5, . . . . . и т. д., всего 100 слов . . . . . . . . ЕSEG SEGMENT PARA PUBLIC ‘DATA’ DEST DW 100 DUP (? ) CSEG SEGMENT PARA PUBLIC ‘CODE’ ASSUME CS: CSEG, DS: DSEG, SS: STACK, ES: ESEG . . . . . . . .. . . . . . . . . . .. CLD LEA SI, SOURCE LEA DI, ES: DEST MOV CX, 100 REP MOVS DEST, SOURCE В этом фрагменте следует обратить внимание на оператор загрузки адреса из дополнительного сегмента в регистр DI. Запись адреса ES: DEST содержит ссылку на полный адрес операнда в памяти ЭВМ: сегментную составляющую адреса в регистре ES и смещение относительно этой составляющей DEST. Такую запись следует применять для адресации любых данных из дополнительного сегмента данных.
Вообще-то ЭВМ можно “обмануть” и выполнять команды работы со строками, находящимися в одном сегменте данных, например, следующим образом: DSEG SEGMENT PARA PUBLIC ‘DATA’ SOURCE DW 1, 2, 3, 4, 5, . . . . . и т. д., всего 100 слов . . . . . . . . DEST DW 100 DUP (? ) CSEG SEGMENT PARA PUBLIC ‘CODE’ ASSUME CS: CSEG, DS: DSEG, SS: STACK . . . . . . . . . . PUSH DS POP ES CLD LEA SI, SOURCE LEA DI, DEST MOV CX, 100 REP MOVSW В этом фрагменте в дополнительный сегментный регистр данных занесен тот же адрес, что и в основной сегментный регистр данных (через стек). Микропроцессор будет работать с сегментными регистрами DS и ES как обычно, даже не подозревая, что копирует данные, находящиеся в одном сегменте. Теперь коротко о других командах работы со строками. Команда сканирования SCAS осуществляет поиск в строке, которая индексируется через регистр DI и располагается в дополнительном сегменте данных. Поиск производится путем сравнения элементов строки с содержимым регистра_аккумулятора AL, если строка представляет совокупность байтов и регистра АХ, если строка представляет совокупность слов. Действие команды можно описать так: Содержимое регистра_аккумулятора – содержимое очередного элемента строки. Аналогично команде CMPS могут быть использованы префиксы повторения REPE / REPZ –поиск до первого несовпадения с образцом или REPNE / REPNZ – поиск до первого совпадения с образцом. Команды загрузки используются для извлечения элемента из строки для дальнейшей обработки этого элемента (например, для его изменения). Используется команда в совокупности с командой сканирования в следующем контексте: “найти элемент строки по образцу и извлечь его для изменения” или в контексте: ”найти первое несовпадение в строке и напечатать не совпавший элемент”. Во 2-ом случае для поиска несовпадений используется команда CMPS. В команде LODS в качестве операнда используется источник – строка, индексируемая регистром SI, находящаяся в основном сегменте данных. Действие команды заключается в извлечении элемента, адресуемого парой регистров DS и SI и занесении этого элемента в регистр_аккумулятор AL, если строка представляет совокупность байтов и регистра АХ, если строка представляет совокупность слов. Префиксы для этой команды не нужны. Команда сохранения STOS по своему действию противоположна команде LODS, т. е. она позволяет сохранить значение элемента из аккумулятора в строке. Действие команды заключается в занесении элемента из регистра_аккумулятора AL, если строка представляет совокупность байтов, или регистра АХ, если строка представляет совокупность слов, в приемник, адресуемый парой регистров ES и DI. Префиксы для этой команды могут понадобиться, а могут и не понадобиться, в зависимости от алгоритма обработки данных.
Воспользуйтесь поиском по сайту: ©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...
|