Практическая работа № 2
Тема: "Использование цепочечных команд – команд обработки строк (CPU i8086/i8088).
Цель работы:
Познакомиться с особенностями выполнения команд обработки строк. На практике изучить преимущество цепочечных команд над командами, работающими с отдельными элементами.
Теоретический материал, который необходим для данной работы:
см. приложение Таблица Команды строковых примитивов.
Особенности работы с перечисленными в таблице командами:
Команды перемещения (копирования) MOVS (Move String Data) переносят данные из места отправления, адрес в DS:SI, в место получения, адрес в ES:DI.
Команда CMPS сравнивает операнд-отправитель (DS:SI) с операндом-получателем (ES:DI). Если строка операнда-отправителя меньше, чем операнда-получателя, CF=1. Если строки равны, ZF=1. Если строка операнда-отправителя > операнда-получателя, CF=0 и ZF=0. Условные переходы, используемые командой CMPS, приведены в таблице:
Условие | Без знака | Со знаком |
source < dest | JB | JL |
source < = dest | JBE | JLE |
source > < dest | JNE (JNZ) | JNE (JNZ) |
source = dest | JE (JZ) | JE (JZ) |
source > = dest | JAE | JGE |
source > dest | JA | JG |
Следует быть особенно внимательными при использовании команды CMPS с условными переходами! Порядок операндов отличается от команды CMP, где сравниваются операнд-получатель с операндом-отправителем (вычитание источника из приемника). В команде CMPS, наоборот, используется вычитание операнда-получателя (приемника) из операнда-отправителя (источника). Например:
Mov ax, 10
cmp ax,5; высчитывает AX - 5
cmps es:dest, source; высчитывает source – dest!!!
Cравнение чисел со знаком. Команда CMPS (Compare String) может сравнивать два списка целых чисел со знаком. В следующем примере каждое число в массиве array1 сравнивается с соответствующими числами в массиве array2.
Data
Array1 dw 3, 9, -7, 15, 10
Array2 dw 3, 9, 8, 15, 10
Code
Cld
Mov si, offset array1
Mov di, offset array2
Mov cx, 5
Repe cmpsw
Jl array1_smaller
Команда SCAS (Scan String) сравнивает значения регистров AL/AX/EAX с байтом, словом или двойным словом по адресу в ES:DI (с операндом-получателем). Эти команды особенно удобны при работе с отдельными символами в длинной строке. В комбинации с префиксом repe (или rep) можно производить сканирование строки, только когда значение в регистре-аккумуляторе совпадает со значением в памяти. С префиксом repne производится сканирование до тех пор, пока значение в регистре-аккумуляторе не совпадает со значением в памяти или СХ=0.
Сканирование для совпадающих символов. В следующем примере строка alpha сканируется до тех пор, пока символ F не будет найден. Когда символ F будет обнаружен, регистр DI будет указывать на первый байт после этого символа и значение регистра надо декрементировать, чтобы он указывал на символ F.
Data
Alpha db 'ABCDEFGH',0
Code
Mov di, seg alpha
Mov ds, di
Mov di, offset alpha; сейчас ES:DI указывает на строку
mov al, 'F'; поиск символа 'F'
Mov cx, 8; установили счетчик
Cld; направление вверх
Repne scasb; повторять пока не равно
; выход, если ZF=1 (т.е. символ найден и получили равенство АХ
; и приемника) или CX=0
Jnz exit
; если выход по ZF=1 (нашли символ), уходим на exit
; если выход по CX=0 (символ не найден), идем на следующую команду
Dec di; найден – вернуться на DI
Вы обратили внимание, что сразу после выполнения команды SCASх еще невозможно определить, что именно стало причиной ее завершения: то, что CX=0, или то, уже найден соответствующий символ, причем и то и другое может произойти одновременно. При использовании префикса repnz (repne) обычно используют команду jnz для перехода, когда символ найден. В этом случае руководствуются следующим принципом – если флаг нуля сброшен, символ не найден, а установленный флаг нуля говорит о том, что символ найден.
Команды сохранения STOS (Store in String) сохраняют содержимое регистров AL/AX/EAX в памяти по адресу ES:DI. Также можно использовать STOS для инициализации памяти единственным значением.
Например: инициализировать каждый байт строки str1 значением 0Ah.
Data
Str1 db 100 dup (?)
Code
Mov di, seg str1
Move es, di; определим адрес сегмента
Mov al, 0ah; заносим значение для заполнения байтов строки
Mov di, offset str1; определим адрес получателя ES:DI
Mov cx, 100; счетчик символов
Cld; направление вверх
rep stosb; заполнить содержимым
Команды загрузки LODS (Load String) загружают из памяти по адресу, указанному в DS:SI, байт или слово в регистры AL/AX/EAX. Префиксы повторения редко используются с командами LODS, потому что каждое новое значение, загружаемое в регистры AL/AX, разрушает их прежние значения. Вместо отдельной команды LODSB можно использовать следующие две команды:
mov al, [si]
Inc si
Следует помнить, что строковые команды имеют следующие особенности:
- позволяют обрабатывать два операнда, находящиеся в оперативной памяти. Оба операнда заданы по умолчанию;
- могут работать в паре со специальными командами, которые называются префиксами повторения. В паре с префиксами повторения строковые команды работают в цикле и обрабатывают поля (цепочки) байт или слов. Поэтому эти команды называют также командами обработки цепочек;
- при выполнении команды анализируется флаг направления DF. Этот флаг не является признаком результата выполнения каких-либо команд. Для работы с ним предусмотрены специальные команды cld - сброс флага DF, std - установка флага DF.
- в командах неявно заданы операнды: первый называется приемником и адресуется регистрами ES:DI, второй называется источником и адресуется регистрами DS:SI. Например, команда movsb(w) выполняет передачу байта (слова) источника в поле приемника. Если DF=0, то передача в прямом направлении, иначе (DF=1) - в обратном направлении.
Контрольные вопросы:
1. Особенности выполнения изучаемых базовых команд процессора i8086/i8088.
2. Команды безусловного перехода.
3. Команды условного перехода. Организация разветвлений.
4. Разница в организации условных переходов для знаковых и беззнаковых данных.
5. Команды управления циклом.
6. Основные особенности работы с цепочечными командами: хранение строки-источника и строки-приемника, флаг направления, использование регистров SI и DI.
7. Целочисленный массив как строка в ассемблере.
8. Префикс повторения.
9. Понятие о байтах кода операции, способах адресации, регистрах и смещениях.
10. В следующем примере необходимо сравнить два массива целых чисел. В той точке, где массивы различаются необходимо поместить наименьший элемент массива в регистр AX. Проверьте и откорректируйте все логические ошибки:
Data
List01 dw -1, 2, -4, 20
List02 dw -1, 2, 3, 20
Code
Cld
Lea si, list01
Lea di, list02
Mov cx,4
Repe cmpsw
Jl L1
Dec si
mov ax, [si]; переместить list01 в AX
Jmp L2
L1: sub di,2
mov ax, [di]; переместить list02 в AX
L2: ret