Обучающие курсы:

Обучение профессии "Разработчик C#" + стажировка в Mail.ru
Обучение профессии "Разработчик Python" + трудоустройство
Обучение профессии "Веб-разработчик" + стажировка в Mail.ru


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





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

6.6. Ассемблерные процедуры в Delphi 7
Встроенный ассемблер Delphi 7 обладает еще одной замечательной возможностью. Процедуры можно писать на "чистом" ассемблере. В этом случае ассемблерные команды помещаются в блок asm-end процедуры. При этом отпадает необходимость в использовании системной переменной ©Result для возвращения результата. Ключевое слово assembler, которое используется до сих пор в более ранних версиях Delphi для обозначения ассемблерной процедуры, более можно не использовать. Рассмотрим подробнее некоторые аспекты написания таких процедур.
Возьмем в качестве примера процедуру сложения двух чисел. На ассемблере она могла бы выглядеть так, как представлено в листинге 6.17.
Листинг 6.17. Процедура сложения двух чисел на ассемблере
function AddTwo(il, i2: Integer): Integer;
asm
mov EAX, DWORD PTR il
add EAX, DWORD PTR i2
end;

Сравните ее с процедурой, использующей блок begin-end (листинг 6.18).
Листинг 6.18. Процедура сложения двух чисел с использованием блока b e g i n - e n d
function AddTwo(il, i2: Integer): Integer;
begin
asm
mov
mov
add
EAX, DWORD PTR il
EAX, DWORD PTR i2
@Result, EAX
end;
end;

Для ассемблерных процедур компилятор выполняет следующие действия по оптимизации:
• при копировании параметров, представляющих собой значения переменных, в локальные переменные никакой дополнительный код не генерируется;
для возвращения результата выполнения процедуры не используется системная переменная @Resuit, кроме тех случаев, когда возвращаемым значением является строка;
компилятор генерирует код пролога и эпилога процедуры, если используется фрейм стека. Это выполняется для вложенных процедур и процедур, использующих локальные параметры или стек. В общем виде такая последовательность действий может быть представлена следующим образом:
push ЕВР
mov ЕВР, ESP
sub ESP, Locals
mov ESP, EBP
pop EBP
ret Params

В этом фрагменте идентификаторы Locals и Params обозначают размеры (в байтах), занимаемые, соответственно, локальными переменными процедуры и параметрами.
Если в процедуру не передаются параметры и не используются локальные переменные, то компилятор генерирует на выходе только команду ret.
Строки:
push ЕВР
mov ЕВР, ESP
pop ЕВР
будут всегда присутствовать, если в процедуру передаются параметры или в самой процедуре задействованы локальные переменные.
Строки:
sub ESP, Locals
mov ESP, EBP

будут присутствовать в тех случаях, если в процедуре задействованы локальные переменные. Наконец, строка ret Params будет присутствовать всегда.
Если в процедуре используются локальные переменные, то при инициализации они всегда устанавливаются в 0.
Ассемблерная процедура возвращает результат в соответствии со следующими правилами:
- порядковые переменные возвращаются в регистре ЕАХ;
- вещественные переменные возвращаются в вершине стека ST(0) математического сопроцессора;
- указатели на переменные (в том числе и на строки) возвращаются в регистре ЕАХ.

Давайте заглянем внутрь ассемблерной процедуры и проанализируем код, который генерирует для нас компилятор. Для этого воспользуемся отладчиком Delphi 7. В качестве объекта анализа возьмем уже знакомую нам процедуру сложения двух целых чисел AddTwo (листинг 6.17) и модифицируем исходный листинг так, чтобы можно было складывать вместе 4 числа (листинг 6.19).
Листинг 6.19. Процедура: сложения 4-х чисел на ассемблере
function AddFour(il, i2, i3, i4: Integer): Integer;
asm
mov EAX, il
add EAX, i2
add
add
end;
ЕАХ, i3
ЕАХ, i4

Приложение, использующее процедуру AddFour, представляет собой окно Windows с одной кнопкой Buttoni и одним полем редактирования Editl.
Исходный текст обработчика нажатия кнопки приведен в листинге 6.20.
Листинг 6,20. Обработчик кнопки Button!, в котором выполняется домминирование чисел
procedure TForml.ButtonlClick(Sender: TObject);
var «
II, 12, 13, 14, ISum: Integer;
begin
11 := 3;
12 := -4;
13 := 1;
14 := 7;
ISum := AddFour(II, 12, 13, 14);
Editl.Text := IntToStr(ISum);
end;

Выполним отладку нашего приложения при помощи встроенного отладчика Delphi 7. Нас будет интересовать тот участок кода, где происходит вызов процедуры AddFour.


 
 
 

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