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

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


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





Анализ работы приложения начнем с ассемблерной процедуры SumReals.
В качестве входных параметров мы передаем процедуре адрес массива вещественных чисел, порядковый номер первого элемента выделенного диапазона (параметр fr, минимальное значение равно 0, что соответствует началу массива), порядковый номер последнего элемента выделенного диапазона (параметр lr). Адрес массива помещаем в регистр E S I , а порядковые номера первого и последнего элементов, соответственно, в регистры EDX И ЕСХ. Далее вычисляем общее количество суммируемых элементов:
sub ЕСХ, EDX
shl EDX, 2
add ESI, EDX

После выполнения этих команд в регистре ЕСХ будет содержаться количество суммируемых элементов, а в регистре E S I — смещение первого элемента последовательности. Команда:
shl EDX, 2
переводит порядковый номер первого элемента, участвующего в суммировании, в эквивалентное ему смещение в байтах от начала массива, поэтому смысл следующей команды:
add ESI, EDX
становится очевиден.

Результирующее значение процедура возвращает в регистре ЕАХ. Для вывода вещественного числа в поле редактирования Edit воспользуемся процедурой FioatToStrF. Она встречалась нам в главе 3, но вспомним, что эта процедура выполняет преобразование вещественного числа в строку символов с использованием опций форматирования, задаваемых программистом. Поскольку процедура SumReals возвращает адрес переменной, то, выполняя разыменование указателя, получим искомое значение суммы.

Можно упростить процедуру вычисления суммы. Встроенный ассемблер позволяет нам получить результат математической операции из вершины стека сопроцессора, минуя регистр ЕАХ! После некоторых изменений исходный текст процедуры SumReals будет выглядеть так, как представлено в листинге 6.26.
Листинг 6.26. Процедура, возвращающая значение через вершину стека сопроцессора
function SumReals(var fa; fr, lr: Integer): Single;
asm
push ESI
mov ESI, DWORD PTR fa
mov EDX, DWORD PTR fr
mov ECX, DWORD PTR lr
sub ECX, EDX
shl EDX, 2
add ESI, EDX
finit
fid DWORD PTR [ESI]
@L1:
fadd DWORD PTR [ESI+4]
add ESI, 4
loop @L1
fwait
pop ESI
end;

Обратите внимание на изменения в исходном тексте программы. Во-первых, исчезли следующие команды:
fstp DWORD PTR fsum

Первая команда нужна была для того, чтобы сохранить значение суммы в памяти, вторая — чтобы вернуть адрес переменной, в которой хранится результат, в основную программу. Поскольку в вершине стека сопроцессора находится теперь значение, а не адрес, то нужно заменить тип возвращаемого процедурой результата на single. Заголовок нашей процедуры будет теперь выглядеть так:
function SumReals(var fa; fr, lr: Integer): Single;
а сама процедура возвращает значение, а не адрес.

В следующем примере определим порядковый номер элемента в массиве вещественных чисел. Для разработки этого примера ограничимся массивом из 7 элементов. Наше приложение будет иметь главную форму с размещенными на ней компонентами. Будем использовать два поля редактирования Edit с именами Editl и Edit2, две метки Label и кнопку Button с именем Buttonl.

Работающее приложение ожидает ввода вещественного числа в поле редактирования Editl, после чего выполняет поиск элемента в массиве. Если элемент найден, то в поле Edit2 выводится номер его позиции в массиве. Если элемент не найден, то выводится сообщение "value not found!". Исходный текст программы представлен в листинге 6.27.
mov EAX, offset fsum

Листинг 6.27. Программа, определяющая позицию элемента в массиве вещественных чисел
unit pospas;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
type
TForml = class(TForm)
Buttonl
Editl
Edit2
Labell
Label2
TButton;
TEdit;
TEdit;
TLabel;
TLabel;
procedure ButtonlClick(Sender: TObject)
private
{ Private declarations }
public
{ Public declarations }
end;
Forml: TForml;
farray: array [1..8] of Single = (2.1, 11.9, 3.2, -4.3, 5.4,
6.5, -7.6, -8.7);
la,rray: Integer;
fVal: Single;
fpos: Integer;
implementat ion
{$R *.dfm}
function RetPos(var farray; Iarray: Integer; fVal: Single): Integer;
asm
462 Гпава 6
push ESI
mov ESI, DWORD PTR farray
mov EDX, ESI
mov ECX, DWORD PTR larray
dec ECX
f init
fldz
fid DWORD PTR fVal
@next:
fcom DWORD PTR [ESI]
fstsw AX
sahf
je @found
add ESI, 4
loop @next
xor EAX, EAX
jmp @exit
@found:
sub ESI, EDX
shr ESI, 2
mov EAX, ESI
@exit:
pop ESI
fwait
end;
procedure TForml.ButtonlClick(Sender: TObject);
begin
larray:= SizeOf(farray) div 4;
fVal:= StrToFloat(Editl.Text) ;
fpos:= RetPos(farray, larray, fVal);
if fpos < larray then
Edit2.Text:= IntToStr(fpos)
else
Edit2.Text:= 'Value not found!';
end;
end.

Проанализируем работу процедуры RetPos. Вначале полученные из основной
программы параметры загружаются в соответствующие регистры. Адрес
массива загружается в регистры E S I И EDX, размер массива — в ЕСХ. Операция
сравнения введенного числа с элементами массива выполняется с использованием
математического сопроцессора.


 
 
 

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