Главная страница
Библиотека (скачать книги)
Скачать софт
Введение в программирование
Стандарты для C++
Уроки по C#
Уроки по Python
HTML
Веб-дизайн
Ассемблер в среде Windows
ActiveX
Javascript
Общее о Линукс
Линукс - подробно
Линукс - новое
Delphi
Паскаль для начинающих
Турбопаскаль
Новости
Партнеры
Наши предложения
Архив новостей
|
Проанализируем ассемблерные команды, показанные в окне отладчика. Для
начала представим дизассемблированный фрагмент кода в более читабельном
виде:
mov
mov
mov
mov
push
mov
call
mov
EAX, 3
EDX, -4
ESI, 1
EDI, 7
EDI
ECX, ESI
AddFour
ESI, EAX
Продолжив отладку программы, попадаем внутрь процедуры AddFour.
Нас будет интересовать код дизассемблированной процедуры, представленный
в листинге 6.21.
Листинг 6.21. Код, сгенерированный отладчиком для процедуры AddFour
push
mov
mov
add
EBP
EBP, ESP
EAX, EAX
EAX, EDX
add ЕАХ, ЕСХ
add ЕАХ, [ЕВР+8]
pop ЕВР
ret 4
Сравнивая последние два листинга, можно сделать следующие выводы:
ассемблерные процедуры в Delphi 7 по умолчанию используют соглашение
о передаче параметров типа register. Как видно из листинга, первые
три параметра передаются в регистрах Е А Х ( И ) , EDX(I2) И ЕСХСЕЗ).
Четвертый параметр 14 передается в регистре EDI через стек;
компилятор автоматически генерирует код пролога и эпилога, если для
передачи параметров используется стек:
push ЕВР
mov ЕВР, ESP
pop ЕВР
ret 4
процедура возвращает результат в регистре ЕАХ.
Модифицируем исходный текст процедуры AddFour, точнее, строку с декларацией
процедуры следующим образом:
function AddFour(il, i2, i3, i4: Integer): Integer; stdcaii;
Запустим приложение на отладку. Нас по-прежнему будут интересовать участки
кода, где вызывается процедура AddFour. В первом окне вы видите
фрагмент кода, где выполняется подготовка передачи параметров в процедуру
Интересующий нас фрагмент кода представлен далее в листинге 6.22.
Листинг 6.22. Передача параметров в процедуру AddFour с использованием соглашения s t d c a i i
mov ЕАХ, 3
mov EDX, -4
mov ESI, 1
mov EDI, 7
454 Глава 6
push EDI
push
push
push
call
mov
ESI
EDX
EAX
AddFour
ESI, EAX
Как видно из листинга, все параметры передаются через стек, причем последний
параметр 14 попадает в стек первым. Возвращаемое процедурой
значение помещается в регистр ЕАХ. Внутри самой процедуры параметры
обрабатываются так, как показано в окне дизассемблера
Представим дизассемблированный текст в более читабельном виде (листинг
6.23).
Листинг 6.23. Обработка данных в процедуре AddFour для соглашения stdcaii
push ЕВР
mov ЕВР, ESP
mov ЕАХ, [ЕВР+8]
add ЕАХ, [ЕВР+12]
add ЕАХ, [ЕВР+16]
add ЕАХ, [ЕВР+20]
pop ЕВР
ret 16
Как и следовало ожидать (и это видно из последних двух листингов), передача
параметров выполняется в соответствии с директивой stdcaii, причем
компилятор генерирует весьма эффективный код! На основании дизассемб-
лированных листингов можно сделать такой вывод: процедура, написанная
полностью на встроенном ассемблере Delphi, практически эквивалентна
отдельно написанному ассемблерному модулю. Теперь можно преобразовать
процедуру вычисления суммы элементов целочисленного массива sumArray
"смешанного" типа в полностью ассемблерный вариант. Она будет выглядеть
так, как представлено в листинге 6.24.
Листинг 6.24. Ассемблерный вариант процедуры SumArray "смешанного" типа
function SumArray(var iaddr; cnt: Integer): Pinteger;
asm
push ESI
mov ESI, DWORD PTR iaddr
mov ECX, DWORD PTR cnt
dec ECX
finit
fild DWORD PTR [ESI]
@L1:
fiadd DWORD PTR [ESI+4]
add ESI, 4
loop @L1
f istp
fwait
DWORD PTR isum
mov EAX, offset isum
pop ESI
end;
Рассмотрим более сложный пример ассемблерной процедуры. Пусть требуется
найти сумму элементов массива, начиная с элемента и заканчивая
к-м. Массив состоит из 7 вещественных чисел.
На главной форме приложения должны быть размещены поля редактирования
Edit с именем Editl для вывода результата и кнопка Button. Вычисление
суммы элементов выполняется в ассемблерной процедуре, возвращающей
в качестве результата указатель на ячейку памяти, содержащую искомое значение.
Обратите внимание, как передаются и используются параметры при
вызове процедуры. Исходный текст программы приведен в листинге 6.25.
Листинг 6.25. Программа, выполняющая подсчет суммы элементов
в определенном диапазоне изменения индекса массива
unit partsum;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls,
Forms, Dialogs, StdCtrls;
type
TForml = class(TForm)
Buttonl: TButton;
Editl : TEdit;
Edit2 : TEdit;
Edit3 : TEdit;
Labell : TLabel;
Label2 : TLabel;
Label3 : TLabel;
procedure ButtonlClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Forml: TForml;
farray: array [1..7] of Single = (4.3, -1.2, 0.5, 7.45, -6.15,
12.3, -3.85);
fr, lr: Integer;
fsum: Single;
implementation
{$R *.dfm}
function SumReals(var fa; fr, lr:
asm
push ESI
mov ESI, DWORD PTR fa
mov EDX, DWORD PTR fr
mov ECX, DWORD PTR lr
Integer): PSingle;
sub ECX, EDX
shl EDX, 2
add ESI, EDX
f init
fid DWORD PTR
@L1:
fadd DWORD PTR [ESI+4]
add ESI, 4
loop @L1
fstp DWORD PTR fsum
fwait
mov EAX, offset fsum
pop ESI
end;
procedure TForml.ButtonlClick(Sender: TObject);
begin
fr := StrToInt(Editl.Text);
lr := StrToInt(Edit2.Text);
Edit3.Text := FloatToStrF((SumReals(farray, fr, 1г)л),
ffGeneral, 5, 7);
end;
end.
<< Назад В начало Далее >> |
|