Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ВМСиС.docx
Скачиваний:
23
Добавлен:
22.04.2019
Размер:
278.98 Кб
Скачать

31.Процессор х86: строковый примитив копирования данных.

Инструкции для работы с участками памяти или строковые примитивы позволяют за один прием без изменения значения программного счетчика выполнить копирование участка памяти, инициализацию участка памяти (заполнение всех ячеек определенным значением), сравнение двух участков памяти. Участки памяти могут рассматриваться как последовательности байт(b), слов(w) или двойных слов(d). Данные инструкции значительно превосходят по эффективности участки кода на языках высокого уровня, предназначенные для выполнения аналогичных задач. Это объясняется тем, что в строковых примитивах адреса источника и приемника модифицируются аппаратно параллельно с обработкой данных, в то время как на языках высокого уровня для этого используются дополнительные машинные инструкции, выполняемые последовательно с обработкой данных. Кроме того, в строковых примитивах осуществляется операция копирования из памяти в память без загрузки и выгрузки данных в один из регистров, как это происходит в программах на языках высокого уровня.

Инструкция копирования строк имеет мнемокод movsb/movsw/movsd. Окончание инструкции b, w или d указывает на размер обрабатываемых данных: байт, слово или двойное слово соответственно. Эти инструкции безоперандные, т.е. приемник и источник не указываются явно за мнемокодом инструкции. В этом нет необходимости, поскольку они всегда адресуются через указательные регистры ESI (источник) и EDI (приемник). Эти инструкции также обычно используются с префиксом повторения REP; при наличии данного префикса количество повторов определяется содержимым регистра-счетчика ECX. После каждого повтора содержимое регистров ESI и EDI изменяется на 1 при копировании байт, на 2 при копировании слов и на 4 при копировании двойных слов. Направление копирования, т.е. увеличение или уменьшение содержимого регистров ESI и EDI определяется состоянием флага направления FD. Если флаг FD сброшен, то копирование осуществляется от младших адресов к старшим; если установлен, то от старших адресов к младшим. Флаг FD можно сбросить инструкцией CLD и установить инструкцией STD.

Пример:

Копирование массива S1 в массив S2.

const int N=200;

short S1[N], S2[N];

_asm{

cld

mov ecx, N

lea edi, S2

lea esi, S2

rep movsw

}

32.Процессор х86: строковые примитивы сравнения данных, сканирования данных и заполнения данных.

Инструкция сравнения строк имеет мнемокод cmpsb/cmpsw/cmpsd и использует регистры ESI, EDI и флаг направления FD, также как и инструкция копирования строк. Но данная инструкция осуществляет не копирование данных, а вычитает из ячейки памяти, указываемой через ESI, содержимое ячейки памяти, указываемой через EDI при этом устанавливается или сбрасывается флаг нуля FZ. Инструкция сравнения используется совместно с префиксами REPNZ (повторять пока не 0) и REPZ (повторять пока 0), позволяющими найти первое совпадение или несовпадение в двух областях памяти.

Пример:

Найти индекс первых несовпадающих элементов в массивах S1 и S2.

const int N=200;

short S1[N], S2[N];

int i;

_asm{

cld

mov ecx, N

lea edi, S2

lea esi, S2

mov eax, esi

repz cmpsw

sub esi, eax

shr esi, 1

mov i, esi

}

Инструкция сканирования строки имеет мнемокод scasb/scasw/scasd и сравнивает содержимое регистра аккумулятора AL/AX/EAX с элементами массива, адрес которого помещен в регистр EDI. Сканирование, также как и сравнение строк, осуществляется совместно с префиксами REPNZ и REPZ и позволяет найти позицию символа в строке или позицию первого символа, отличающегося от заданного.

Пример:

Найти индекс нуль-терминатора в строке S (длину строки).

const int N=200;

char S[N];

int L;

_asm{

cld

mov ecx, N

lea edi, S

mov ebx, edi

mov al, 0

repnz scasb

sub edi, ebx

mov L, edi

}

Инструкция сохранения строки имеет мнемокод stosb/stosw/stosd и позволяет инициализировать массив, адресуемый через EDI, значением, содержащемся в аккумуляторе AL/AX/EAX.

Пример:

Обнулить массив M.

const int N=200;

int M[N];

_asm{

cld

mov ecx, N

lea edi, M

mov eax, 0

rep stosd

}

Поскольку операции копирования и инициализации массивов часто встречаются в прикладных программах, а использование встроенного ассемблера для обращения к строковым примитивам не всегда возможно, то в большинство языков программирования ввели специальные функции, которые являются оболочками над строковыми примитивами и поэтому выполняются практически также быстро, как и ассемблерные вставки. В частности в стандартной библиотеке языка C имеются следующие функции:

void *memset(void *s, int c, size_t n);

s – адрес участка памяти

с – байт, которым будет забиваться участок памяти

n – количество байт для заполнения

void *memmove(void *dest, const void *src, size_t n);

dest – адрес приемника

srs – адрес источника

n – количество копируемых байт

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