Главная страница
Библиотека (скачать книги)
Скачать софт
Введение в программирование
Стандарты для C++
Уроки по C#
Уроки по Python
HTML
Веб-дизайн
Ассемблер в среде Windows
ActiveX
Javascript
Общее о Линукс
Линукс - подробно
Линукс - новое
Delphi
Паскаль для начинающих
Турбопаскаль
Новости
Партнеры
Наши предложения
Архив новостей
|
Вначале немного теории. Хочу напомнить, что мы работаем только с 32-
разрядными приложениями. Такие приложения используют модель памяти
fiat и работают только с 32-разрядными операционными системами
Windows 98/Windows NT/Windows 2000/Windows XP. Для такой модели не
существует отдельных сегментов данных и кода. Пространство адресов считается
линейным, и в нем располагаются код и данные, которые используют
32-разрядные смещения, а вызовы процедур и функций считаются ближними.
Такой режим работы обеспечивает высокую производительность 32-
разрядных приложений, т. к. нет преобразования "сегмент-смещение" в абсолютные
адреса. Кроме того, 32-разрядные приложения "не видят" друг
друга и выполняются в изолированном от других приложений пространстве
адресов. Это очень сильно отличает их от 16-разрядных приложений, где
все программы могли "видеть" друга.
Итак, основные принципы работы ассемблерных процедур в программах на
языках высокого уровня мы разобрали. Далее, следуя принципу "лучший
критерий истины — практика", перейдем к рассмотрению примеров программного
кода. Мы будем рассматривать примеры вначале на Delphi, затем
на Visual С++. Для совместной работы наших ассемблерных модулей и программ
на языках высокого уровня будем использовать соглашение о передаче
параметров stdcaii.
Рассмотрим следующий пример. Пусть требуется найти разность двух целых
чисел и вывести результат в окно приложения. Вычисление разности суммы
чисел выполним в ассемблерной процедуре, скомпилированной как отдельный
модуль. Результат вычитания выведем в окно основного приложения.
Назовем нашу процедуру на ассемблере subtwo.
Исходный текст процедуры subtwo приведен в листинге 3.20.
Листинг 3.20. Ассемблерная процедура subtwo, вычисляющая разность двух
целых чисел, для использования в Delphi .
.386
.model flat, stdcaii
public subtwo
.data
. code
subtwo proc
push EBP
mov EBP, ESP
mov EAX, DWORD PTR [EBP+8]
sub EAX, DWORD PTR [EBP+12]
pop EBP
ret 8
subtwo endp
end
Сохраним исходный текст процедуры в файле subtwo.asm и откомпилируем
программу при помощи одной из двух командных строк в зависимости от
вида компилятора ассемблера:
tasm32 /ml subtwo.asm subtwo.obj
ml /с /Fo subtwo.obj subtwo.asm
Если в тексте программы нет ошибок, мы получим объектный файл
subtwo.obj, готовый к употреблению.
Для передачи параметров в процедуру subwo используется стек. Для доступа
к параметрам мы используем регистр ЕВР, текущее значение которого процедура
сохраняет в стеке. Помним, что мы имеем дело с 32-разрядными
операндами, поэтому первый параметр и будет иметь смещение в стеке на
8 (с учетом помещенного в стек ЕВР), а второй параметр 12 — смещение 12
относительно вершины стека
Расположение параметров в стеке соответствует соглашению для директивы
stdcaii. Сама процедура вычитает числа и возвращает результат в регистре
ЕАХ. Согласно stdcaii вызываемая процедура должна сама восстанавливать
(очищать) стек. Перед последней командой ret возвращаемое
значение уже находится в регистре ЕАХ, а в стеке все еще присутствуют два
параметра. Хочется сделать несколько общих замечаний по работе с внешними процедурами
и функциями. Они касаются не только процедуры subtwo.
1. Желательно сохранять в стеке регистры ЕВХ, ЕВР, E S I И E D I , Т. К. ОНИ могут
использоваться операционной системой, и разрушение их содержимого
может привести к неприятным последствиям. Регистры ЕАХ, EDX И ЕСХ
можно использовать по своему усмотрению, не заботясь об их сохранении.
2. В 32-разрядных приложениях понятие "сегментный регистр" отсутствует.
Если пытаться по аналогии с MS-DOS использовать регистры cs, ES И DS,
то это немедленно приведет к краху программы.
3. Не забывайте освобождать стек при выходе из процедуры при использовании
директив pascal, stdcaii и safecaii. Количество удаляемых байт
равно количеству параметров, умноженному на 4. К примеру, для удаления
из стека 3-х параметров необходимо в процедуре последней вызвать
команду ret 12.
Вместо ret п можно использовать комбинацию команд:
add ESP, n
ret
Вернемся к нашему примеру. Разработаем программу на языке высокого
уровня, вызывающую нашу процедуру subtwo. Начнем с Delphi 7. Наша
программа будет представлять собой обычное оконное приложение
Windows. Разместим на главной форме приложения три поля редактирования
Edit и назовем их HEdit, i2Edit и subResuit. Поле редактирования
HEdit будем использовать для ввода числа и, поле i2Edit —
для ввода 12 и поле subResuit — для отображения результата вычитания 12
из 11. Слева от полей редактирования поместим три метки статического
текста Label.
Разместим на форме также кнопку Button. При нажатии этой кнопки в работающем
приложении в поле редактирования subResuit будет отображаться
результат вычитания.
Теперь внесем изменения в исходный текст программы. В секцию implementation
добавим описание нашей процедуры subtwo:
implementation
{$R *.dfm}
{$L subtwo.obj}
Последняя строка сообщает компоновщику, какой внешний модуль будет
использоваться в основной программе. В данном случае это файл subtwo.obj.
<< Назад В начало Далее >> |
|