Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Учебн пособ по арх и прогр МП.doc
Скачиваний:
64
Добавлен:
10.12.2013
Размер:
1.59 Mб
Скачать

13.8 КомандыEnter иLeave

В системе ко­манд микропроцессора имеются специальные команды enter и leave. Их использование позволяет облегчить написание кода пролога и эпилога в про­цедурах ассемблера, например:

;старый код пролога:

push bp

mov bp, sp

; новый код пролога:

enter 0,0

; … … …

; старый код эпилога:

mov sp, bp

pop bp

;новый код эпилога:

leave

Транслятор ассемблера предоставляет средства в виде директив, которые еще больше упрощают работу программиста по формированию кодов пролога и эпилога. Одной из них является директива arg.

Применение директив arg и local приводит к генерации команд enter и leave при входе и выходе из процедуры. Поочередное комментирование этих директив по­казывает, что они влияют только на формирование операнда команды enter. При использовании local он равен числу байт, необходимых для размещения в стеке локальных переменных. Это так называемый кадр стека. Если строку с директи­вой local закомментировать, то команда enter все равно формируется, но с нуле­вым значением первого операнда. Это говорит о том, что пролог процедуры фор­мируется в любом случае, но директива local позволяет еще и сформировать кадр стека для хранения локальных переменных процедуры. Соответственно, во всех вариантах генерации команды enter в конце процедуры формируется команда leave.

Отметим, что эти средства можно использовать не только для связи Pascal - ассемблер, но и для организации других - межъязыковых связей, в том числе ассемблер - ассемблер.

13.9 Итоги

Язык ассемблера содержит достаточно мощные средства поддержки структурного программирования. В языке ассемблера эта технология поддерживается в основном с помощью механизма процедур и частично с использованием макрокоманд.

Гибкость интерфейса между процедурами достигается за счет разнообразия вариантов передачи аргументов в процедуру и возвращения результатов. Для этого могут использоваться регистры, общие области памяти, стек, директивы extrn и public.

Средства TASM поддерживают связи между языками. Ключевой момент при этом - организация обмена данными. Обмен данными между процедурами на языках высокого уровня и ассемблера производится через стек. Для доступа к аргументам используется регистр bp или (что более удобно) директива arg.

Тема 15. СозданиеWindows-приложения на ассемблере КаркасноеWindows-приложение на языке С/С++.

Мы начинаем с программы на языке С/С++. Во-первых, нам необходимо понять общие принципы построения оконных приложений Windows. Во-вторых мы разберемся с тем, какие средства ассемблера при этом используются.

Приступая к разработке первого Windows-приложения, важно понимать, что сам язык программирования мало влияет на его общую структуру. Это обстоятельство и позволит нам чуть позже с относительной легкостью изменить инструментальное средство разработки Windows-приложения с С/С++ на ассемблер.

Выполнение любого оконного Windows-приложения начинается с главной функции. Она содержит код, осуществляющую настройку приложения в среде операционной системы Windows. Видимым для пользователя результатом работы главной функции является появление на экране графического объекта в виде окна. Последним действием кода главной функции является создание цикла обработки сообщений. Обработка поступающих приложению сообщений осуществляется специальной функцией, называемой оконной. Тело оконной функции имеет определенную структуру. Таким образом, Windows-приложение, как минимум, должно состоять из трех перечисленных элементов. В листинге 1.1 приведен вариант минимального приложения на языке С/С++.

Листинг 1.1. КаркасноеWindows-приложение на языке С/С++

#include <windows.h>

LRESULT CALLBACK WindowProc(HWND ,UINT ,WPARAM ,LPARAM);

char szClassWindow[] = "КаркасноеПриложение"; /*Имя класса окна*/

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpszCmdLine, int nCmdShow)

{

HWND hWnd;

MSG lpMsg;

WNDCLASSEX wcl;

/* Определение класса окна */

wcl.cbSize = sizeof (wcl); //длина структуры WNDCLASSEXA

wcl.style = CS_HREDRAW|CS_VREDRAW; //CS (Class Style) - стиль класса окна

wcl.lpfnWndProc = WindowProc; //адрес функции окна

wcl.cbClsExtra =0; //для внутреннего использования Windows

wcl.cbWndExtra = 0; //для внутреннего использования Windows

wcl.hInstance = hInst; //дескриптор данного приложения

wcl.hIcon = LoadIconA(NULL,IDI_APPLICATION); //стандартная иконка

wcl.hCursor = LoadCursorA(NULL,IDC_ARROW); //стандартный курсор

wcl.hbrBackground =(HBRUSH)GetStockObject (WHITE_BRUSH); // определить заполнение окна белым цветом

wcl.lpszMenuName = NULL; //без меню

wcl.lpszClassName = szClassWindow; //имя класса окна

wcl.hIconSm=NULL; //дескриптор маленькой иконки, связываемой с классом окна

//зарегистрировать класс окна

if (!RegisterClassEx (&wcl))

return 0;

//создать окно и присвоить дескриптор окна переменной hWnd

hWnd=CreateWindowEx(

0, //расширенный стиль окна

szClassWindow, //имя класса окна

"Каркас программы для Win32 на С++", //заголовок окна

WS_OVERLAPPEDWINDOW, //стиль окна

CW_USEDEFAULT, //X-координата верх. левого угла окна

CW_USEDEFAULT, //Y-координата верх. левого угла окна

CW_USEDEFAULT, //ширина окна

CW_USEDEFAULT, //высота окна

NULL, //дескриптор родительского окна

NULL, //дескриптор меню окна

hInst, //идент. приложения создавшего окно

NULL); //указатель на область данных приложения

//показать окно и перерисовать содержимое

ShowWindow (hWnd, nCmdShow);

UpdateWindow (hWnd);

/* запустить цикл обработки сообщений */

while (GetMessage(&lpMsg,NULL,0,0))

{

TranslateMessage(&lpMsg); //разрешить использование клавиатуры

DispatchMessage(&lpMsg); //вернуть управление Windows

}

return lpMsg.wParam;

} //конец WinMain

LRESULT CALLBACK WindowProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

//Функция WndProc вызывается операционной системой Windows 95

//и получает в качестве параметров сообщения из очереди

//сообщений данного приложения

{

switch(message)

{

case WM_DESTROY: /* завершение программы */

PostQuitMessage (0);

break;

default:

//Сюда попадают все сообщения, не обрабатываемые в данной оконной функции.

//Далее эти сообщения направляются обратно Windows на обработку по умолчанию

return DefWindowProc (hWnd, message, wParam, lParam);

}

return 0;

}

Разберем долее подробно суть действии, выполняемых каждым из трех элементов Windows-приложения. В листинге 1.1 видно, что минимальное приложение на языке С/С++ состоит из 2-х функции: главной-WinMain и оконной-WindowProc. Цель WinMain- сообщить системе о новом для нее приложения, его свойствах и особенностях.

Оконная функция получает все сообщения, предназначенные данному окну, и обрабатывает их.

Видимая часть работы каркасного приложения заключается в создании нового окна на экране. Оно отвечает всем требованиям стандартного окна приложения Windows.

В процессе формирования объектного модуля компилятор преобразует исходный текст на языке С/С++ в эквивалентный текст на языке ассемблера. В контексте нашего обсуждения это достаточно ценная информация.

Полученный текст на ассемблере ценен тем, что в нем каждой строке исходного текста программы на языке С/С++ сопоставляется текст на ассемблере. В листинге 1.2 приведен текст.