Книги
чёрным по белому
Главное меню
Главная О нас Добавить материал Поиск по сайту Карта книг Карта сайта
Книги
Археология Архитектура Бизнес Биология Ветеринария Военная промышленность География Геология Гороскоп Дизайн Журналы Инженерия Информационные ресурсы Искусство История Компьютерная литература Криптология Кулинария Культура Лингвистика Математика Медицина Менеджмент Металлургия Минералогия Музыка Научная литература Нумизматика Образование Охота Педагогика Политика Промышленные производства Психология Путеводители Религия Рыбалка Садоводство Саморазвитие Семиотика Социология Спорт Столярное дело Строительство Техника Туризм Фантастика Физика Футурология Химия Художественная литература Экология Экономика Электроника Энергетика Этика Юриспруденция
Новые книги
Цуканов Б.И. "Время в психике человека" (Медицина)

Суворов С. "Танк Т-64. Первенец танков 2-го поколения " (Военная промышленность)

Нестеров В.А. "Основы проэктирования ракет класса воздух- воздух и авиационных катапульных установок для них" (Военная промышленность)

Фогль Б. "101 вопрос, который задала бы ваша кошка своему ветеринару если бы умела говорить" (Ветеринария)

Яблоков Н.П. "Криминалистика" (Юриспруденция)
Реклама

Использование ассемблера для оптимизации программ на С++ - Магда Ю.С.

Магда Ю.С. Использование ассемблера для оптимизации программ на С++ — БХВ-Петербург , 2004. — 496 c.
ISBN 5-94157-414-2
Скачать (прямая ссылка): ispolzovaniyaassemblera2004.djvu
Предыдущая << 1 .. 9 10 11 12 13 14 < 15 > 16 17 18 19 20 21 .. 127 >> Следующая

Чтобы развернуть цикл, будем одновременно выполнять копирование двух двойных слов. Исходный текст оптимизированного фрагмента кода показан в листинге 1.5 (необходимые изменения выделены жирным шрифтом).
i I и с: и и ¦ 1.5 Ру:ич'.Г:нчивннио цикли дмух
mov ESI, src mov EDI, dst
; значение счетчика поместим в регистр ЕСХ
mov ЕСХ, count
; значение счетчика делим на 8 (используются двойные ; слова!)
shr ЕСХ, 3
label:
читаем первое двойное слово в регистр ЕАХ
34
Часть /. Основы эффективного программирования на ассемблере
mov ЕАХ, [ESI]
; читаем второе двойное слово в регистр ЕВХ mov ЕВХ, [ESI + 4]
; записываем первое двойное слово в регистр EDI
mov [EDI], ЕАХ
; записываем второе двойное слово по адресу в EDI на 4 ; больше предыдущего
mov [EDI + 4], ЕВХ
; продвигаем адреса источника и приемника так, чтобы они ; указывали на следующее двойное слово
add ESI, 8 add EDI, 8
; анализ конца цикла
dec ЕСХ jnz label
Применение подобной техники уменьшит замедление программы, привнесенное циклом, наполовину. Можно и далее развернуть цикл, если оперировать не двумя, а четырьмя двойными словами.
Еще один пример разворачивания циклов. Пусть имеется массив из 20-ти целых чисел. Необходимо присвоить элементам массива с четными номерами (О, 2, 4 и т. д.) значение 0, а элементам с нечетными номерами — значение 1.
Решение задачи "в лоб" показано в листинге 1.6.
помещаем число элементов массива в регистр ЕСХ
Гпава 1. Оптимизация ассемблерного кода для процессоров Pentium
35
mov ЕСХ, 20
; помещаем адрес первого элемента массива в регистр ESI lea ESI, il
; помещаем делитель 2 в регистр ЕВХ для использования при определении' ; четного-нечетного элемента
mov ЕВХ, 2 next:
; помещаем счетчик элементов в регистр ЕАХ mov ЕАХ, ЕСХ
; определяем: четный или нечетный порядковый номер элемента массива
div ЕВХ cmp EDX, 0
; если нечетный, присваиваем элементу значение 1 jne set_l
; если четный, присваиваем элементу значение 0
mov DWORD PTR [ESI], 0 jmp LI set_l:
mov DWORD PTR [ESI], 1 LI:
; переход к адресу следующего элемента массива
add ESI, 4 loop next
36
Часть I. Основы эффективного программирования на ассемблере
Этот фрагмент программного кода можно оптимизировать, если оперировать в одной итерации двумя двойными словами. Исходный текст модифицированного варианта кода показан в листинге 1.7 (курсивом выделены команды ассемблера, которые мы убираем).
¦ Листинг 1.7. Инициализация масс-'иа
mov EDX, О ; mov ЕСХ, 20 lea ESI, il ,* mov ЕВХf 2 next:
; mov EfiX, ECX ; div EBX ; cmp EDX, 0
mov DWORD PTR [ESI] , 0 mov DWORD PTR [ESI+4], 1 add EDX, 2
; jmp LI ;set_l:
; mov DWORD PTR [ESI], 1
;L1:
cmp EDX, 19 jae ex add ESI, 8
jmp next
ex:
В исходном тексте этого фрагмента кода есть существенные отличия по сравнению с исходным текстом листинга 1.6. Мы избавились от команд деления и одновременно уменьшили число итераций в два раза (команда add edx, 2 выделена жирным шрифтом). В каждой итерации обрабатываются одновременно два элемента массива (команды mov dword ptr [esi] , о и mov dword ptr [esi+4], l выделены жирным шрифтом). В конце каждой итерации содержимое регистра esi увеличивается на 8 с помощью команды'add esi, 8, указывая на следующую пару элементов.
Гпава 1. Оптимизация ассемблерного кода для процессоров Pentium
37
Разработаем простое консольное приложение в C++ .NET 2003, в котором используется оптимизированный алгоритм. В этом приложении вызывается функция initarr из отдельного ассемблерного модуля, которая и выполняет обработку массива.
Я пока не буду анализировать интерфейс ассемблерных функций и программы на C++, это будет сделано в следующих главах. Основная задача этого примера — продемонстрировать технику оптимизации ассемблерного кода, поэтому сосредоточимся именно на ней.
Исходный текст оптимизированного ассемблерного модуля, содержащего функцию initarr и адаптированного для компиляции в среде макроассемблера MASM 6.14, показан в листинге 1.8.
Листинг 1,8. Инициализация мэссмва (иариан!' для MASM G. 14) .686
.model flat public _initarr .code
_initarr proc
; пролог функции
push EBP mov EBP, ESP
; в регистр ЕСХ помещается размер массива, а в регистр ; ESI — адрес первого элемента
mov ЕСХ, DWORD PTR [ЕВР+12]
mov ESI, DWORD PTR [EBP+8]
mov EDX, 0
dec ECX
next:
mov DWORD PTR [ESI], 0 mov DWORD PTR [ESI+4], 1 add EDX, 2
cmp EDX, ECX
jae ex
38
Часть I. Основы эффективного программирования на ассемблере
add ESI, 8 jmp next
ex:
; эпилог функции
pop EBP ret
_initarr endp end
Исходный текст консольного приложения C++ .NET показан в листинге 1.9.
¦ Л истине 1.3. Инициализации и отображение муссивз целых чисел
// UNROLL_LOOP_OPT.срр : Defines the entry point for the console // application.
linclude "stdafx.h"
extern "C" void initarr(int* pil, int isize); int _tmain(int argc, _TCHAR* argv[])
{
int il [20];
printf ("UNROLLING LOOP DEMO\n\n"); printf("il[20] = "); initarr(il, 20);
for (int cnt = 0;cnt < 20;cnt++) printf("%d ", il[cnt]); getchar(); return 0;
}
Окно приложения (рис. 1.1) демонстрирует содержимое массива после инициализации.
Предыдущая << 1 .. 9 10 11 12 13 14 < 15 > 16 17 18 19 20 21 .. 127 >> Следующая