Главная страница
Библиотека (скачать книги)
Скачать софт
Введение в программирование
Стандарты для C++
Уроки по C#
Уроки по Python
HTML
Веб-дизайн
Ассемблер в среде Windows
ActiveX
Javascript
Общее о Линукс
Линукс - подробно
Линукс - новое
Delphi
Паскаль для начинающих
Турбопаскаль
Новости
Партнеры
Наши предложения
Архив новостей





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

В нашей программе используется процедура FindDif. В качестве параметров она принимает адреса трех массивов: двух сравниваемых массивов xi и х2 и массива целых чисел itmp, в который записываются номера позиций в массивах, где значения элементов не совпадают. Еще один параметр, необходимый для работы процедуры — размер массива xlen. Поскольку в нашем примере размерность всех массивов одинакова, то не имеет значения, размер какого массива передается в процедуру.

В начале процедуры, как обычно, сохраняем те регистры процессора, которые используются операционной системой. Для работы с элементами массивов xi и х2 помещаем их адреса в регистры E S I И E D I , сохраняем начальное смещение массива xi (оно нам пригодится) в регистре EDX. Также нам потребуется и размер xlen массива xi для организации сравнения элементов в цикле. Его мы сохраняем в регистре ЕСХ. Кроме того, нам необходимо знать адрес массива itmp. Его мы сохраняем в регистре ЕВХ. Все эти действия выполняет следующий фрагмент программного кода ассемблерной процедуры:
push ЕВХ
push ESI
push EDI
mov ESI, xl
mov EDI, х2
mov EDX, ESI
mov EBX, itmp
mov ECX, DWORD PTR xlen

Для выполнения сравнения элемент массива xi помещаем в регистр ЕАХ, а элемент массива х2 находится в памяти, адрес которой содержит регистр EDI:
mov ЕАХ, [ESI]
cmp ЕАХ, [EDI]
jne @store

Если элементы равны, то к адресам текущих элементов добавляется 4, и выполняется очередной цикл сравнения. Если элементы не равны, то выполняется переход на метку @store, где вычисляется позиция неравных элементов в массиве, и номер этой позиции загружается в массив itmp. Каждый раз после очередной записи он увеличивается на 4, указывая место, куда, возможно, будет загружен следующий элемент. После записи позиции элемента в массив itmp и продвижения указателя к следующему адресу цикл сравнения элементов в массивах xl и х2 повторяется. Все эти действия отображены в следующем фрагменте кода:
@store:
mov EAX, E S I
sub EAX, EDX
shr EAX, 2
add EAX, 1
mov [EBX], EAX
add EBX, 4
jmp @next

Обычные арифметические команды сравнения чисел в процедуре FindDif можно заменить командами математического сопроцессора. В этом случае исходный текст процедуры изменится и будет выглядеть так, как представлено в листинге 6.29.
Листинг 6.29. Процедура до в которой используются команды сопроцессора procedure FindDif(var xl, х2, itmp; xlen: Integer);
asm
push EBX
push ESI
push EDI
mov ESI, xl
mov EDI, x2
mov EDX, ESI
mov EBX, itmp
mov ECX, DWORD PTR xlen
sub ESI, 4
sub EDI, 4
f init
fldz
@again:
add ESI, 4
add EDI, 4
fid [ESI]
fcomp [EDI]
fstsw AX
sahf
jne @store
@next:
dec ECX
cmp ECX, 0
jnz @again
jmp @exit
@store:
mov EAX, ESI
sub EAX, EDX
shr EAX, 2
add EAX, 1
mov [EBX], EAX
add EBX, 4
jmp @next
@exit:
fwait
pop EDI
pop ESI
pop EBX
end;

Здесь блок команд сравнения элементов выглядит несколько иначе, т. к. используется математический сопроцессор:
fid [ESI]
fcomp [EDI]
fstsw AX
sahf
jne @store
@next:

Команда fid загружает число из массива xi (его адрес находится в регистре E S I ) В вершину стека сопроцессора. Следующая команда fcomp выполняет сравнение числа в стеке с элементом массива х2 (его адрес находится в EDI). В результате сравнения устанавливаются соответствующие биты (сз, С2, со) в регистре состояния сопроцессора. Команда fstsw сохраняет слово состояния в регистре АХ. ДЛЯ удобства манипуляций с битами слова состояния запишем содержимое старшего байт регистра АХ В регистр флагов при помощи команды sahf.

Нам нужно определить равенство или неравенство двух чисел- Для этого достаточно проанализировать бит установки 0 в регистре ф л а г о в ( Z F — zero flag). Если ZF = о, то числа не равны, и наоборот, если ZF = 1 у к а з ы в а е т на равенство чисел. Далее все происходит так, как и в предыдущем варианте этой процедуры.

Хотелось бы обратить ваше внимание на очень важный момент работы этого приложения. Процедура FindDif не возвращает никакого результата, тем не менее в массиве itmp оказываются нужные значения. Процедуры встроенного ассемблера могут вообще не возвращать никакого з н а ч е н и я , а использовать в качестве "разделяемой памяти" переменные и массивы, адреса которых передаются им в качестве параметров. Термин " р а з д е л я е м а я память" взят в кавычки по той причине, что в операционных с и с т е м а х Windows ,уже существует такое понятие и оно отличается от нашего определения. Тем не менее этот термин достаточно точно отображает суть дела. Программисты довольно часто используют такую методику для обработки переменных и массивов несколькими процедурами.


 
 
 

Библиотека программиста. 2009.
Администратор: admin@programmer-lib.ru