- •Минобрнауки россии
- •Е.В. Грачева Системное программное обеспечение персональных эвм
- •1 Программирование в операционной среде
- •1.1 Программирование в среде однозадачной операционной системы
- •1.2 Программирование в среде ос Windows
- •1.2.1 Основные понятия
- •1.2.2 Программный интерфейс
- •1.2.2.1 Сообщения, очередь сообщений
- •1.2.2.2 Процедура окна
- •1.2.3 Использование динамических библиотек
- •1.2.3.1.Описание api-функции LoadLibrary
- •1.2.3.2 Описание функции GetProcAddress
- •1.2.3.3 Описание функции FreeLibrary
- •1.2.4 Описание некоторых api-функций
- •1.2.4.1.Функции для создания пользовательского интерфейса
- •1.2.4.1.1 Ввод данных с клавиатуры
- •1.2.4.1.2 Ввод данных с помощью "мыши"
- •1.2.4.1.3 Диалоговые окна
- •1.2.4.2 Функции для получения информации о системе
- •1.2.4.2.1 Информация об аппаратной конфигурации
- •1.2.4.2.3 Конфигурация ос
- •1.2.4.2.4 Системные параметры
- •1.2.4.2.5 Внешний вид системных элементов
- •1.2.4.3 Функции управления памятью
- •1.2.4.3.1 Основные функции управления памятью
- •1.2.4.4.Функции управления файлами
- •1.2.4.4 Функции управления некоторыми устройствами
- •Контрольные вопросы
- •35. Охарактеризовать функцию для определения конфигурации ос
- •36. Охарактеризовать функции об установке системных параметров.
- •2.Ассемблеры
- •2.1 Архитектура процессоров ia-32
- •2.1.1.Основная исполнительная среда микропроцессора с архитектурой ia32
- •2.1.2 Режимы работы и используемая модель памяти процессоров с архитектурой ia32
- •2.1.3 Архитектура ia-32 системного уровня
- •2.2.Программирование на языке ассемблера
- •2.2.1 Метки
- •2.2.2 Директивы
- •2.2.3 Формат команды
- •2.2.4 Система команд микропроцессоров с архитектурой ia32
- •2.2.4.1 Команды пересылки данных
- •Ins строка, dx
- •2.2.4.2 Арифметические операции
- •2.2.4.3 Операции сдвига
- •2.2.4.4 Битовые операции
- •2.2.4.5 Команды для организации циклов
- •1.3.1.1 Команды сравнения
- •2.2.4.6 Команды передачи управления
- •2.2.4.7 Системные команды
- •2.2.4.8 Команды математического сопроцессора
- •2.2.5 Технология программирования
- •2.3 Макроязыки
- •3.Трансляторы
- •3.1 Структура компиляторов и интерпретаторов, лексический, синтаксический и семантический анализаторы, генератор кода
- •3.1.1.Распределение памяти, виды переменных
- •3.1.2.Статическое и динамическое связывание
- •3.2 Загрузчики
- •3.2.1 Функции загрузчика
- •3.2.1 Настраивающий и динамический загрузчики
- •3.3 Подключение библиотек
- •4. Формальные языки и грамматики
- •4.1 Типы грамматик
- •4.1.1 Вывод цепочек
- •4.1.2 Конечный и магазинный автоматы, распознаватели и преобразователи, построение автомата по заданной грамматике
- •Приложения Приложение а
- •Оглавление
- •4. Формальные языки и грамматики
Приложения Приложение а
Пример простейшего приложения для ОС Windows на языке Visual С++ (разработан в среде Visual Studio 2008)
-----------------------------------------------------------
#include "stdafx.h"
LRESULT CALLBACK WndProc (HWND hwnd, UINT message,WPARAM wParam, LPARAM lParam);
BOOL InitApplication (HINSTANCE hInstance);
BOOL InitInstance (HINSTANCE hInstance, int nCmdShow);
LPCSTR szClassName = "CLASS32";
LPCSTR szTitle = "Простейшее 32-х разрядное приложение на Visual C++ (Visual Studio 2008)";
int WINAPI WinMain (
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
if (!hPrevInstance)
{
if (!InitApplication(hInstance))
return FALSE;
};
if (!InitInstance(hInstance,nCmdShow))
return FALSE;
MSG msg;
while (GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
};
typedef struct tagMSG
{
HWND hwnd;
UINT message;
WPARAM wParam;
LPARAM lParam;
DWORD time;
POINT pt;
}
MSG;
return static_cast<int>(msg.wParam);
}
BOOL InitApplication (HINSTANCE hInstance)
{
WNDCLASS wc;
wc.style = CS_HREDRAW|CS_VREDRAW|CS_GLOBALCLASS;
wc.lpfnWndProc = static_cast<WNDPROC>(WndProc);
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL,IDI_EXCLAMATION);
wc.hCursor = LoadCursor(NULL,IDC_HAND);
wc.hbrBackground = reinterpret_cast<HBRUSH>(2);
wc.lpszMenuName = NULL;
wc.lpszClassName = szClassName;
return RegisterClass(&wc);
}
BOOL InitInstance(HINSTANCE hInstance,int nCmdShow)
{
HWND hWnd;
hWnd = CreateWindowEx (
NULL,
szClassName,
szTitle,
WS_OVERLAPPEDWINDOW,
100,
100,
400,
400,
NULL,
NULL,
hInstance,
NULL);
if (!hWnd)
return(FALSE);
if (ShowWindow(hWnd,SW_SHOW))
return(FALSE);
if (!UpdateWindow(hWnd))
return (FALSE);
return TRUE;
}
LRESULT CALLBACK WndProc(
HWND hwnd,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
switch (message)
{
case WM_LBUTTONDOWN:
MessageBox(NULL,"Нажата левая клавиша мыши","Сообщение",MB_OK);
break;
case WM_RBUTTONDOWN:
MessageBox(NULL,"Нажата правая клавиша мыши","Сообщение",MB_OK);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}
----------------------------------------------------------------------------------
Пример простейшего приложения для ОС Windows на языке ассемблера (masm32) [4].
Строка программы |
Комментарий |
||||||||
Директивы ассемблеру MASM32 |
|||||||||
.386P |
Младшая модель процессора, поддерживающая представленные в программе команды |
||||||||
.MODEL FLAT, stdcall |
Используемая модель памяти, формат передачи параметров в процедуры |
||||||||
Объявления констант |
|||||||||
Константы, определяющие коды сообщений посылаемых операционной системой ЗНАЧЕНИЯ КОНСТАНТ можно найти в заголовочном файле WINUSER.H |
|||||||||
WM_DESTROY equ 2 |
Сообщение приходит при закрытии окна |
||||||||
WM_CREATE equ 1 |
Сообщение приходит при создании окна |
||||||||
WM_LBUTTONDOWN equ 201h |
Код нажатия левой клавиши мыши |
||||||||
WM_RBUTTONDOWN equ 204h |
Код нажатия правой клавиши мыши |
||||||||
Константы, определяющие свойства окна (подробное назначение констант можно найти в [Error: Reference source not found], значение констант определяется в заголовочном файле WinUser.h системы программирования Microsoft VisualStudio) |
|||||||||
CS_VREDRAW equ 1h CS_HREDRAW equ 2h CS_GLOBALCLASS equ 4000h; style equ CS_HREDRAW+CS_VREDRAW+CS_GLOBALCLASS |
|
||||||||
WS_OVERLAPPEDWINDOW equ 000080000H |
|
||||||||
IDI_EXCLAMATION equ 32515; |
идентификатор иконки в заголовке окна |
||||||||
IDC_HAND equ 32649 |
идентификатор курсора |
||||||||
SW_SHOWNORMAL equ 1 |
режим показа окна (подробно см. [Error: Reference source not found]): |
||||||||
Прототипы внешних процедур из внешних библиотек, число после @ обозначает количество байт, передаваемых в качестве параметров, ВНИМАНИЕ: команда PUSH передает 2 или 4 байта. Более подробно описание API-функций – в тексте программы |
|||||||||
EXTERN MessageBoxA@16: NEAR |
Создает и отображает блок диалога, содержащий указанное сообщение и заголовок, а также пpедопpеделенные пиктограммы и текстовые кнопки |
||||||||
EXTERN CreateWindowExA@48:NEAR |
Создает перекрытое, всплывающее или дочернее окно с расширенным стилем. |
||||||||
EXTERN DefWindowProcA@16:NEAR |
Обеспечивает стандартную обработку сообщений для сообщений, которые явно не обрабатываются прикладной задачей. |
||||||||
EXTERN DispatchMessageA@4:NEAR |
Передает сообщение оконной функции окна. |
||||||||
EXTERN ExitProcess@4:NEAR |
Завершает процесс |
||||||||
EXTERN GetMessageA@16:NEAR |
Считывает сообщение, из очереди сообщений прикладной задачи. |
||||||||
EXTERN GetModuleHandleA@4:NEAR |
Считывает дескриптор модуля |
||||||||
EXTERN LoadCursorA@8:NEAR |
Загружает указанный тип курсора |
||||||||
EXTERN LoadIconA@8:NEAR |
Загружает указанный тип пиктограммы |
||||||||
EXTERN PostQuitMessage@4:NEAR |
Направляет сообщение wm_Quit, обычно в ответ на сообщение wm_Destroy. |
||||||||
EXTERN RegisterClassA@4:NEAR |
Регистрирует класс окна, атрибуты которого определены параметром WndClass, для последующего использования. Класс окна может регистрироваться только один раз |
||||||||
EXTERN ShowWindow@8:NEAR |
Отображает или прячет окно образом, указанным параметром CmdShow |
||||||||
EXTERN TranslateMessage@4:NEAR |
Пеpеводит комбинации wm_KeyDown/Up в wm_Char или wm_DeadChar и комбинации wm_SysKeyDown/Up в wm_SysChar или wm_SysDeadChar и направляет символьное сообщение в очередь прикладной задачи |
||||||||
EXTERN UpdateWindow@4:NEAR |
Если область обновления окна непуста, то посылает сообщение wm_Paint напрямую оконной функции данного окна. |
||||||||
Директивы компоновщику для подключения библиотек |
|||||||||
includelib d:\masm32\lib\user32.lib |
указывается путь до библиотек, содержащих стандартные функции |
||||||||
includelib d:\masm32\lib\kernel32.lib |
|||||||||
Описания структур данных |
|||||||||
Структура сообщения, посылаемого ОС приложениям |
|||||||||
MSGSTRUCT STRUC |
Начало описания структуры данных |
||||||||
MSHWND DD ? |
переменная для хранения идентификатора окна, получающего сообщение |
||||||||
MSMESSAGE DD ? |
идентификатор сообщения |
||||||||
MSWPARAM DD ? |
доп. информация о сообщении |
||||||||
MSLPARAM DD ? |
доп. информация о сообщении |
||||||||
MSTIME DD ? |
время посылки сообщения |
||||||||
MSPT DD ? |
положение курсора, во время посылки сообщения |
||||||||
MSGSTRUCT ENDS |
Конец описания структуры данных |
||||||||
Структура данных, описывающая стиль окна |
|||||||||
WNDCLASS STRUC |
|
||||||||
CLSSTYLE DD ? |
стиль окна |
||||||||
CLWNDPROC DD ? |
указатель на процедуру окна |
||||||||
CLSCSEXTRA DD ? |
информация о доп. байтах для данной структуры |
||||||||
CLWNDEXTRA DD ? |
информация о доп. байтах для окна |
||||||||
CLSHINSTANCE DD ? |
дескриптор приложения |
||||||||
CLSHICON DD ? |
идентификатор иконы окна |
||||||||
CLSHCURSOR DD ? |
; идентификатор курсора окна |
||||||||
CLBKGROUND DD ? |
идентификатор кисти окна |
||||||||
CLMENUNAME DD ? |
имя-идентификатор меню |
||||||||
CLNAME DD ? |
специфицирует имя класса окон |
||||||||
WNDCLASS ENDS |
|
||||||||
Сегмент данных |
|||||||||
_DATA SEGMENT DWORD PUBLIC USE32 'DATA' |
объявление начала сегмента данных |
||||||||
NEWHWND DD 0 ; |
переменная для хранения дескриптора созданного окна |
||||||||
MSG MSGSTRUCT <?> ; |
переменная для хранения сообщения |
||||||||
WC WNDCLASS <?>; |
переменная для описания окна |
||||||||
HINST DD 0 ; |
переменная для хранения дескриптора приложения |
||||||||
TITLENAME DB 'Простейшее 32-битное приложение на Assembler',0 |
Строка для заголовка окна |
||||||||
CLASSNAME DB 'CLASS32',0; |
класс приложения - 32х разрядное |
||||||||
CAP DB 'Сообщение',0; |
заголовок окна с сообщением о нажатой клавише |
||||||||
LBUTTON_Text DB 'Нажата левая клавиша',0; |
Сообщение о нажатой клавише |
||||||||
RBUTTON_Text DB 'Нажата правая клавиша',0; |
Сообщение о нажатой клавише |
||||||||
_DATA ENDS |
объявление конца сегмента данных |
||||||||
Сегмент кода |
|||||||||
_TEXT SEGMENT DWORD PUBLIC USE32 'CODE'
|
объявление начала сегмента |
||||||||
START: |
точка входа в программу |
||||||||
Инициализация приложения: |
|||||||||
PUSH 0 CALL GetModuleHandleA@4 MOV [HINST], EAX |
получение дескриптора приложения с помощью API функции GetModuleHandle. Предварительно в стек записывается указатель на имя модуля (строку, заканчивающуюся 0). Дескриптор приложения формируется ОС и возвращается приложению через регистр EAX. |
||||||||
Регистрация класса окна приложения |
|||||||||
REG_CLASS: |
заполнить структуру для описания окна: |
||||||||
MOV [WC.CLSSTYLE], style |
переменная WC типа WNDCLASS |
||||||||
MOV [WC.CLWNDPROC], OFFSET WNDPROC ; |
определяется адрес процедуры обработки сообщений WNDPROC |
||||||||
MOV [WC.CLSCSEXTRA], 0 MOV [WC.CLWNDEXTRA], 0 |
|
||||||||
MOV EAX, [HINST] MOV [WC.CLSHINSTANCE], EAX |
Сохраняется дескриптор приложения |
||||||||
Создание иконки окна |
|||||||||
PUSH IDI_APPLICATION |
В стек передается строка или имя целочисленного идентификатора или пиктограммы, определенной одной из констант IDI_. |
||||||||
PUSH 0 |
В стек передается 0, т.к. используется предопределенная пиктограмма (в противном случае передается дескриптор экземпляра модуля, исполнимый файл которого содержит пиктограмму) |
||||||||
CALL LoadIconA@8 |
Вызов API-функции LoadIcon |
||||||||
MOV [WC.CLSHICON], EAX |
В переменную загружается идентификатор пиктограммы |
||||||||
Создание курсора окна |
|||||||||
PUSH IDC_CROSS |
В стек передается строка или имя целочисленного идентификатора или курсор, определенный одной из констант IDI_. |
||||||||
PUSH 0 |
В стек передается 0, т.к. используется предопределенный курсор |
||||||||
CALL LoadCursorA@8 |
Вызов API-функции LoadCursor |
||||||||
MOV [WC.CLSHCURSOR], EAX |
В переменную загружается идентификатор курсора |
||||||||
MOV [WC.CLBKGROUND], 2 |
определяется цвет окна. Например, 0 - белый, 1 - серый (форма), 2 - голубой, 3 - синий, 4 - серый, 7 – черный и т.п. |
||||||||
MOV DWORD PTR [WC.CLMENUNAME], 0; |
имя-идентификатор меню |
||||||||
MOV DWORD PTR [WC.CLNAME], OFFSET CLASSNAME;
|
имя класса |
||||||||
PUSH OFFSET WC |
сохраняется адрес самой переменной WC |
||||||||
CALL RegisterClassA@4 |
Вызов API функции регистрации класса окна |
||||||||
Создание окна зарегистрированного класса |
|||||||||
PUSH 0 |
Значение, переданное в TCreateStruct в параметре lParam сообщения wm_Create. Для создания дочернего окна MDI должно быть указателем на структуру TClientCreateStruct. |
||||||||
PUSH [HINST] |
Дескриптор модуля |
||||||||
PUSH 0 |
Идентификатор меню или дочернего окна. Поскольку нет – 0 |
||||||||
PUSH 0 |
Окно владельца (родительского приложения) |
||||||||
Размеры окна в пикселях. Центр системы координат находится в левом верхнем углу, ось Y направлена вниз, ось Х - вправо. Впрочем, это общепринятый вариант для графических экранов. |
|||||||||
PUSH 400 |
DY — высота окна, переменные типа DD |
||||||||
PUSH 400 |
DX - ширина окна |
||||||||
PUSH 100 |
Y — координата левого верхнего угла |
||||||||
PUSH 100 |
X — координата левого верхнего угла |
||||||||
PUSH WS_OVERLAPPEDWINDOW |
формат окна (см. раздел определения констант) |
||||||||
PUSH OFFSET TITLENAME |
имя окна |
||||||||
PUSH OFFSET CLASSNAME |
имя класса |
||||||||
PUSH 0 |
идентификатор одного из расширенных стилей окна (0 – по умолчанию) |
||||||||
CALL CreateWindowExA@48 |
Вызов API функции создания окна |
||||||||
CMP EAX, 0 JZ _ERR |
проверка на ошибку, если после выполнения API-функции возвращен 0, значит была какая-то ошибка |
||||||||
MOV [NEWHWND], EAX |
сохраняется дескриптор окна |
||||||||
Показ созданного окна |
|||||||||
PUSH SW_SHOWNORMAL |
константа, определяющая формат отображения окна |
||||||||
PUSH [NEWHWND] |
дескриптор окна |
||||||||
CALL ShowWindow@8; |
показать созданное окно |
||||||||
Перерисовка окна |
|||||||||
PUSH [NEWHWND] |
Загружается дескриптор обновляемого окна |
||||||||
CALL UpdateWindow@4 |
API функция для обновления (перерисовки) видимой части окна |
||||||||
Цикл (петля) обработки сообщений |
|||||||||
MSG_LOOP: |
метка начала цикла |
||||||||
PUSH 0 |
0 , поскольку не используется фильтрация сообщений (от клавиатуры или от мыши). Максимальное значение диапазона фильтрации |
||||||||
PUSH 0 |
0 , поскольку не используется фильтрация сообщений (от клавиатуры или от мыши). Минимальное значение диапазона фильтрации |
||||||||
PUSH 0 |
0, поскольку для всех окон в прикладной задаче или дескриптор окна назначения сообщений |
||||||||
PUSH OFFSET MSG |
адрес переменной, хранящей сообщения |
||||||||
CALL GetMessageA@16 |
API функция считывает сообщение, в рамках диапазона фильтрации, из очереди сообщений прикладной задачи |
||||||||
CMP EAX, 0 |
0 – если выход, в противном случае какое-то иное сообщение |
||||||||
JE END_LOOP |
переход если равно 0 |
||||||||
PUSH OFFSET MSG |
Загружается в стек адрес переменной, хранящей сообщения |
||||||||
CALL TranslateMessage@4 |
Перевод комбинации в символьные сообщения и направляет их в очередь прикладной задачи |
||||||||
PUSH OFFSET MSG |
Загружается в стек адрес переменной, хранящей сообщения |
||||||||
CALL DispatchMessageA@4 |
Передает в Msg сообщение оконной функции окна. |
||||||||
JMP MSG_LOOP |
возврат на начало цикла |
||||||||
END_LOOP: |
метка конца цикла |
||||||||
Выход из программы (закрыть процесс) |
|||||||||
PUSH [MSG.MSWPARAM] CALL ExitProcess@4 |
Для выхода из программы используется специальная API функция |
||||||||
_ERR: |
метка, для перехода по ошибке |
||||||||
JMP END_LOOP |
переход на конец цикла Можно было сразу по ошибке переходить на конец цикла, однако по метке _ERR можно вставить процедуру обработки ошибок |
||||||||
Процедура окна |
|||||||||
Расположение параметров в стеке: [EBP+014H] – LPARAM [EBP+10H] – WAPARAM [EBP+0CH] – MES [EBP+08H] – HWND |
|||||||||
WNDPROC PROC |
объявление оконной процедуры |
||||||||
PUSH EBP MOV EBP, ESP |
инициализация указателя стека |
||||||||
PUSH EBX PUSH ESI PUSH EDI |
сохранение регистров |
||||||||
Обработка сообщений |
|||||||||
CMP DWORD PTR [EBP+0CH], WM_DESTROY |
если пришло сообщение на закрытие окна |
||||||||
JE WMDESTROY; |
переход на закрытие окна |
||||||||
CMP DWORD PTR [EBP+0CH], WM_CREATE |
если пришло сообщение на создание окна |
||||||||
JE WMCREATE; |
переход на создание окна |
||||||||
CMP DWORD PTR [EBP+0CH] ,WM_LBUTTONDOWN |
Если нажата левая кнопка |
||||||||
JE LBUTTON; |
переход на обработку нажатия левой клавиши мыши |
||||||||
CMP DWORD PTR [EBP+0CH] ,WM_RBUTTONDOWN |
Если нажата правая кнопка |
||||||||
JE RBUTTON; |
переход на обработку нажатия правой клавиши мыши |
||||||||
JMP DEFWNDPROC; |
переход на вызов API-функции, возвращающей сообщение обратно ОС |
||||||||
Вывод сообщения по нажатию левой кнопки мыши |
|||||||||
LBUTTON: |
|
||||||||
PUSH 00000000h ; |
загружается тип окна (с кнопкой «Ок») |
||||||||
PUSH OFFSET CAP |
адрес заголовка окна с сообщением |
||||||||
PUSH OFFSET LBUTTON_Text |
адрес выводимого сообщения |
||||||||
PUSH DWORD PTR [EBP+08H] |
дескриптор приложения |
||||||||
CALL MessageBoxA@16 |
API функция вывода окна сообщения |
||||||||
MOV EAX, 0 |
Загружается код выхода |
||||||||
JMP FINISH |
Переход на конец оконной процедуры |
||||||||
Вывод сообщения по нажатию правой кнопки мыши |
|||||||||
RBUTTON: |
|
||||||||
PUSH 00000000h |
загружается тип окна (с кнопкой «Ок») |
||||||||
PUSH OFFSET CAP |
адрес заголовка окна с сообщением |
||||||||
PUSH OFFSET RBUTTON_Text |
адрес выводимого сообщения |
||||||||
PUSH DWORD PTR [EBP+08H] |
дескриптор приложения |
||||||||
CALL MessageBoxA@16 |
API функция вывода окна сообщения |
||||||||
MOV EAX, 0 |
Загружается код выхода |
||||||||
JMP FINISH |
Переход на конец оконной процедуры |
||||||||
WMCREATE: |
метка перехода на создание окна |
||||||||
MOV EAX, 0 |
поскольку окно уже создано |
||||||||
JMP FINISH |
переход на конец |
||||||||
DEFWNDPROC: |
метка перехода на вызов API-функции, возвращающей сообщение обратно ОС |
||||||||
PUSH DWORD PTR [EBP+14H] PUSH DWORD PTR [EBP+10H] PUSH DWORD PTR [EBP+0CH] PUSH DWORD PTR [EBP+08H] |
загружаются параметры текущей задачи |
||||||||
CALL DefWindowProcA@16 |
вызов API функции |
||||||||
JMP FINISH |
переход на конец |
||||||||
WMDESTROY: |
метка закрытия окна |
||||||||
PUSH 0 |
код выхода приложения, без ошибок – 0 |
||||||||
CALL PostQuitMessage@4 |
вызов функции посылки сообщения об окончании работы |
||||||||
MOV EAX, 0 |
|
||||||||
FINISH: |
|
||||||||
POP EDI POP ESI POP EBX POP EBP |
восстановление значений регистров |
||||||||
RET 16 |
возврат из процедуры с освобождением 16 байт |
||||||||
WNDPROC ENDP |
конец оконной процедуры |
||||||||
_TEXT ENDS |
конец сегмента |
||||||||
END START |
конец программы |
||||||||
