На этом шаге мы рассмотрим пример, демонстрирующий основы работы с графикой на ассемблере.
Студент 4 курса факультета математики и информационных технологий Курганского государственного университета Брылев Данил Алексеевич представляет ассемблерную программу, иллюстрирующую использование графики. Здесь можно строить линии, закрашенные и незакрашенные прямоугольники и эллипсы. Кроме того реализованы выбор цветов и толщины линий.
Приведем текст программы.
.386 .model flat, stdcall ;Плоская модель. option casemap :none ;Директива говоpит MASM сделать метки ;чувствительными к pегистpу. ;Необходимо для безошибочного подключения ;windows.inc-файла. ;Директивы компоновщику для подключения inc-файлов и библиотек. include \masm32\include\user32.inc include \masm32\include\kernel32.inc include \masm32\include\gdi32.inc include \masm32\include\windows.inc include \masm32\include\comdlg32.inc includelib \masm32\lib\user32.lib includelib \masm32\lib\kernel32.lib includelib \masm32\lib\gdi32.lib includelib \masm32\lib\comdlg32.lib ;=============================== ; Объявление локальных макросов ;=============================== szText MACRO Name, Text:VARARG LOCAL lbl jmp lbl Name db Text,0 lbl: ENDM m2m MACRO M1, M2 push M2 pop M1 ENDM return MACRO arg mov eax, arg ret ENDM ;========================================= ; Объявление прототипов локальных функций ;========================================= WinMain PROTO :DWORD,:DWORD,:DWORD,:DWORD WndProc PROTO :DWORD,:DWORD,:DWORD,:DWORD TopXY PROTO :DWORD,:DWORD .data ;Название нашего окна szDisplayName db "Графика в окне",0 ;Дескриптор коммандной строки CommandLine dd ? ;Дескриптор окна hWnd dd ? ;Дескриптор приложения hInstance dd ? ;Дескриптор главного меню hMenu dd ? ;Дескриптор контекста для хранения постоеного изображения hMemBkDC dd ? ;Дескриптор контекста для хранения строящегося изображения hMemDC dd ? ;Дескрипторы используемых карандашей и кистей hPen dd ? hLBrush dd ? hRBrush dd ? hLSPen dd ? hRSPen dd ? ;Информация о текущих основном и дополнительном цветах RColor dd 000000h ;clBlack LColor dd 000080h ;clMaroon ;Структура для хранения координат вершин прямоугольника клиентской области cRect RECT <?> ;Координаты начальной и текущей точек рисуемых объектов sPosX dd ? sPosY dd ? cPosX dd ? cPosY dd ? ;Текущий рисуемый объект: 0-ничего,1-лин,2-элл,3-к.элл,4-прям,5-к.прям sFF db ? ;Текущий выбранный объект: 1-лин,2-элл,3-к.элл,4-прям,5-к.прям cFF db 1 ;Текущая толщина линий sPen dd 3 ;Текущие размеры экрана XM dd ? YM dd ? ;Информация о текущих выбранных пунктах меню Menu103 dd 10301h Menu104 dd 10401h Menu105 dd 10500h Menu106 dd 10603h ;Получаем цвет фона RGBW equ (80 or (80 shl 8)) or (255 shl 16) ;Массив используемых нами цветов Color dd 000000h ;clBlack dd 000080h ;clMaroon dd 008000h ;clGreen dd 008080h ;clOlive dd 800000h ;clNavy dd 800080h ;clPurple dd 808000h ;clTeal dd 808080h ;clGray dd 0C0C0C0h ;clSilver dd 0000FFh ;clRed dd 00FF00h ;clLime dd 00FFFFh ;clYellow dd 0FF0000h ;clBlue dd 0FF00FFh ;clFuchsia dd 0FFFF00h ;clAqua dd 0C0C0C0h ;clLtGray dd 808080h ;clDkGray dd 0FFFFFFh ;clWhite ;Структура для ChooseColor диалога cc CHOOSECOLOR <?> ;Массив дополнительных цветов ChooseColor диалога CCCustColors dd 000000h ;clBlack dd 000080h ;clMaroon dd 008000h ;clGreen dd 008080h ;clOlive dd 800000h ;clNavy dd 800080h ;clPurple dd 808000h ;clTeal dd 808080h ;clGray dd 0C0C0C0h ;clSilver dd 0000FFh ;clRed dd 00FF00h ;clLime dd 00FFFFh ;clYellow dd 0FF0000h ;clBlue dd 0FF00FFh ;clFuchsia dd 0FFFF00h ;clAqua dd 0FFFFFFh ;clWhite .code start: invoke GetModuleHandle, NULL ;Получить дескриптор приложения mov hInstance, eax invoke GetCommandLine ;Получить дескриптор коммандной строки mov CommandLine, eax invoke WinMain,hInstance,NULL,CommandLine,SW_SHOWDEFAULT invoke ExitProcess,eax ;Выход из программы (завершить процесс). WinMain proc hInst :DWORD, hPrevInst :DWORD, CmdLine :DWORD, CmdShow :DWORD ;=============================== ; Вводим "локальные" переменные ;=============================== LOCAL wc :WNDCLASSEX LOCAL msg :MSG LOCAL Wwd :DWORD LOCAL Wht :DWORD LOCAL Wtx :DWORD LOCAL Wty :DWORD szText szClassName,"Class32" ;Имя класса ;================================================ ; Заполняем WNDCLASSEX структуру нужными данными ;================================================ mov wc.cbSize, sizeof WNDCLASSEX mov wc.style, CS_HREDRAW + CS_VREDRAW + CS_SAVEBITS + CS_OWNDC mov wc.lpfnWndProc, offset WndProc mov wc.cbClsExtra, NULL mov wc.cbWndExtra, NULL m2m wc.hInstance, hInst ;Декскриптор кисти фона (NULL-фон рисоваться не будет) mov wc.hbrBackground, NULL mov wc.lpszMenuName, NULL mov wc.lpszClassName, offset szClassName ;Читаем стандартную иконку invoke LoadIcon,7F00h,0 mov wc.hIcon, eax ;Читаем курсор с идентификатором 1000 из ресурсов приложения invoke LoadCursor,hInst,3e8h mov wc.hCursor, eax mov wc.hIconSm, 0 invoke RegisterClassEx, ADDR wc ;Регистрируем класс "Class32" ;Получаем информацию о размерах экрана и по заданным длине ;и ширине окна находим центральное расположение окна mov Wwd, 500 mov Wht, 300 invoke GetSystemMetrics,SM_CXSCREEN mov XM,eax invoke TopXY,Wwd,eax mov Wtx, eax invoke GetSystemMetrics,SM_CYSCREEN mov YM,eax invoke TopXY,Wht,eax mov Wty, eax ;Создаем окно зарегестрированного класса invoke CreateWindowEx,0, ADDR szClassName, ADDR szDisplayName, WS_OVERLAPPED + WS_CAPTION + WS_SYSMENU + \ WS_MINIMIZEBOX + WS_MAXIMIZEBOX + WS_THICKFRAME, Wtx,Wty,Wwd,Wht, NULL,NULL, hInst,NULL mov hWnd,eax invoke LoadMenu,hInst,2 ;Читаем меню с идентификатором 2 mov hMenu,eax invoke SetMenu,hWnd,eax ;Привязываем его к нашему окну ;Показываем созданное окно invoke ShowWindow,hWnd,SW_SHOWNORMAL ;Перерисовываем содержимое окна invoke UpdateWindow,hWnd ;========================== ; Цикл обработки сообщений ;========================== StartLoop: invoke GetMessage,ADDR msg,NULL,0,0 cmp eax, 0 je ExitLoop invoke DispatchMessage, ADDR msg jmp StartLoop ExitLoop: return msg.wParam WinMain endp ;Функция обработки сообщений главного окна WndProc proc hWin :DWORD, uMsg :DWORD, wParam :DWORD, lParam :DWORD ;=============================== ; Вводим "локальные" переменные ;=============================== LOCAL hDC :DWORD LOCAL Ps :PAINTSTRUCT .if uMsg == WM_MOUSEMOVE ;Получаем информацию о текущем рисуемом объекте, ;Если ничего не рисуем, то смысла прорисовывать окно нет .if sFF == 0 return 0 .endif ;Получаем координаты точки местонахождения курсора ;и задаем их как координаты текущей точки рисования mov ecx, 0h mov cx, WORD PTR [lParam] mov cPosX, ecx mov cx, WORD PTR [lParam+2h] mov cPosY, ecx ;Копируем изображение с контекста MemBkDC на MemDC ;и дорисовываем русуемый объект в текущем положении invoke BitBlt,hMemDC,0,0,XM,YM,hMemBkDC,0,0,SRCCOPY .if sFF == 1 invoke MoveToEx,hMemDC,sPosX,sPosY,NULL invoke LineTo,hMemDC,cPosX,cPosY .elseif sFF == 2 invoke Ellipse,hMemDC,cPosX,cPosY,sPosX,sPosY .elseif sFF == 4 invoke Rectangle,hMemDC,cPosX,cPosY,sPosX,sPosY .elseif sFF == 3 invoke Arc,hMemDC,cPosX,cPosY,sPosX,sPosY,0,0,0,0 .elseif sFF == 5 invoke MoveToEx,hMemDC,sPosX,sPosY,NULL invoke LineTo,hMemDC,cPosX,sPosY invoke LineTo,hMemDC,cPosX,cPosY invoke LineTo,hMemDC,sPosX,cPosY invoke LineTo,hMemDC,sPosX,sPosY .endif ;Перерисовываем содержимое окна invoke RedrawWindow,hWin,NULL,NULL,RDW_INVALIDATE return 0 .elseif uMsg == WM_PAINT invoke BeginPaint,hWnd,ADDR Ps mov hDC,eax ;Копируем изображение с контекста MemDC на контекст окна invoke BitBlt,hDC,0,0,cRect.right,cRect.bottom,hMemDC,0,0,SRCCOPY invoke EndPaint,hWnd,ADDR Ps return 0 .elseif uMsg == WM_LBUTTONDOWN ;Получаем координаты точки нажатия кнопки мыши ;и задаем их как координаты начальной точки рисования ;И эти же координаты задаем координатми текущей точки, ;чтобы не возникало рисования фигуры из прошлой текущей точки ;при нажатии и отпускании кнопки в одной и той же точке без движения mov ecx, 0h mov cx, WORD PTR [lParam] mov sPosX, ecx mov cPosX, ecx mov cx, WORD PTR [lParam+2h] mov sPosY, ecx mov cPosY, ecx ;Задаем информацию о текущем рисуемом объекте(sFF) в соответствии с ;выбранным инструментом(cFF) mov cl,cFF mov sFF,cl ;Выбираем карандаши и кисти в зависимости от рисуемого объекта .if (cFF == 1) || (cFF == 3) || (cFF == 5) invoke SelectObject,hMemDC,hLSPen .elseif (cFF == 2) || (cFF == 4) invoke SelectObject,hMemDC,hPen invoke SelectObject,hMemDC,hLBrush .endif return 0 .elseif uMsg == WM_RBUTTONDOWN mov ecx, 0h mov cx, WORD PTR [lParam] mov sPosX, ecx mov cPosX, ecx mov cx, WORD PTR [lParam+2h] mov sPosY, ecx mov cPosY, ecx mov cl,cFF mov sFF,cl .if (cFF == 1) || (cFF == 3) || (cFF == 5) invoke SelectObject,hMemDC,hRSPen .elseif (cFF == 2) || (cFF == 4) invoke SelectObject,hMemDC,hPen invoke SelectObject,hMemDC,hRBrush .endif return 0 .elseif uMsg == WM_LBUTTONUP ;Завершаем рисование копированием полученного изображения mov sFF,0 invoke BitBlt,hMemBkDC,0,0,XM,YM,hMemDC,0,0,SRCCOPY return 0 .elseif uMsg == WM_RBUTTONUP mov sFF,0 invoke BitBlt,hMemBkDC,0,0,XM,YM,hMemDC,0,0,SRCCOPY return 0 .elseif uMsg == WM_COMMAND cmp wParam,10101h ;<<<< Пункт меню "Файл" -> "Выход" jne @F invoke SendMessage,hWin,WM_SYSCOMMAND,SC_CLOSE,NULL return 0 @@: cmp wParam,10201h ;<<<< Пункт меню "Правка" -> "Очистить" jne @F ;Здесь мы не выбираем кисть для контекста MemBkDC, так как не меняли ;ее после заполнения его изображения в момент создания окна invoke PatBlt,hMemBkDC,0,0,XM,YM,PATCOPY invoke BitBlt,hMemDC,0,0,XM,YM,hMemBkDC,0,0,SRCCOPY invoke RedrawWindow,hWin,NULL,NULL,RDW_INVALIDATE return 0 @@: ;Обрабатываем выбор пунктов меню "Инструменты" cmp wParam,10301h jb @F cmp wParam,10305h ja @F ;Сбрасываем "галочку" у прошлого выбранного пункта invoke CheckMenuItem,hMenu,Menu103,MF_UNCHECKED m2m Menu103,wParam ;Ставим "галочку" у соответствующего пункта меню invoke CheckMenuItem,hMenu,wParam,MF_CHECKED ;Получаем относительный номер выбранного подпункта ;(Последний байт идентификатора) mov cl,Byte Ptr [wParam] ;Выбираем текущий инструмент mov cFF,cl return 0 @@: ;Обрабатываем выбор пунктов меню "Инструменты" -> "Основной цвет" cmp wParam,10400h jb @F cmp wParam,10412h ja @F invoke CheckMenuItem,hMenu,Menu104,MF_UNCHECKED m2m Menu104,wParam invoke CheckMenuItem,hMenu,wParam,MF_CHECKED ;Если выбран пункт "Другой...", то вызываем ChooseColor диалог. ;И задаем информацию о текущем выбранном основном цвете LColor .if wParam == 10412h m2m cc.rgbResult,LColor invoke ChooseColor,offset cc m2m LColor,cc.rgbResult .else xor ecx,ecx mov cl, Byte Ptr [wParam] m2m LColor,DWord Ptr [Color+ecx*4] .endif ;Создаем кисть и карандаш выбранного цвета invoke DeleteObject,hLBrush invoke DeleteObject,hLSPen invoke CreateSolidBrush,LColor mov hLBrush,eax invoke CreatePen,PS_SOLID,sPen,LColor mov hLSPen,eax return 0 @@: ;Обрабатываем выбор пунктов меню "Инструменты" -> "Дополнительный цвет" cmp wParam,10500h jb @F cmp wParam,10512h ja @F invoke CheckMenuItem,hMenu,Menu105,MF_UNCHECKED m2m Menu105,wParam invoke CheckMenuItem,hMenu,wParam,MF_CHECKED .if wParam == 10512h m2m cc.rgbResult,RColor invoke ChooseColor,offset cc m2m RColor,cc.rgbResult .else xor ecx,ecx mov cl, Byte Ptr [wParam] m2m RColor,DWord Ptr [Color+ecx*4] .endif invoke DeleteObject,hRBrush invoke DeleteObject,hRSPen invoke CreateSolidBrush,RColor mov hRBrush,eax invoke CreatePen,PS_SOLID,sPen,RColor mov hRSPen,eax return 0 @@: ;Обрабатываем выбор пунктов меню "Инструменты" -> "Толщина линий" cmp wParam,10601h jb @F cmp wParam,10605h ja @F invoke CheckMenuItem,hMenu,Menu106,MF_UNCHECKED m2m Menu106,wParam invoke CheckMenuItem,hMenu,wParam,MF_CHECKED xor ecx,ecx mov cl, Byte Ptr [wParam] mov sPen, ecx ;Создаем новые карандаши выбранной толщины invoke DeleteObject,hRSPen invoke DeleteObject,hLSPen invoke CreatePen,PS_SOLID,sPen,RColor mov hRSPen,eax invoke CreatePen,PS_SOLID,sPen,LColor mov hLSPen,eax @@: return 0 .elseif uMsg == WM_SIZE ;Получаем информацию о текущих размерах клиентской области окна invoke GetClientRect,hWin,ADDR cRect return 0 .elseif uMsg == WM_CREATE ;Получаем дескриптор контекста окна. invoke GetDC,hWin mov hDC,eax ;Создаем совместимые с данным контекстом контексты. invoke CreateCompatibleDC,eax mov hMemBkDC, eax invoke CreateCompatibleDC,hDC mov hMemDC, eax ;Создаем в памяти растровое изображение, совместимое с hDC. invoke CreateCompatibleBitmap,hDC,XM,YM ;Выбраем растровое изображение в данном контексте. invoke SelectObject,hMemBkDC,eax invoke CreateCompatibleBitmap,hDC,XM,YM invoke SelectObject,hMemDC,eax ;Создаем кисть цвета фона и заполняем ей растровые изображения контекстов invoke CreateSolidBrush,RGBW mov hLBrush,eax invoke SelectObject,hMemBkDC,eax invoke PatBlt,hMemBkDC,0,0,XM,YM,PATCOPY invoke SelectObject,hMemDC,hLBrush invoke PatBlt,hMemDC,0,0,XM,YM,PATCOPY ;Освобождаем контекст и удаляем кисть invoke ReleaseDC,hWin,hDC invoke DeleteObject,hLBrush invoke GetClientRect,hWin,ADDR cRect ;Создаем невидимый карандаш, используемый ;интсрументами "Прямоугольник" и "Эллипс" invoke CreatePen,PS_NULL,1,0 mov hPen,eax ;Создаем карандаши и кисти начальных цветов и заданных парамметров invoke CreatePen,PS_SOLID,sPen,LColor mov hLSPen,eax invoke CreatePen,PS_SOLID,sPen,RColor mov hRSPen,eax invoke CreateSolidBrush,RColor mov hRBrush,eax invoke CreateSolidBrush,LColor mov hLBrush,eax ;Заполняем CHOOSECOLOR структуру, для вызова ChooseColor диалога mov cc.lStructSize, sizeof CHOOSECOLOR m2m cc.hwndOwner, hWin m2m cc.hInstance, hInstance mov cc.lpCustColors, offset CCCustColors mov cc.Flags, CC_RGBINIT return 0 .elseif uMsg == WM_DESTROY ;Удаляем созданные объекты invoke DeleteObject,hRSPen invoke DeleteObject,hLSPen invoke DeleteObject,hPen invoke DeleteObject,hRBrush invoke DeleteObject,hLBrush invoke DeleteDC,hMemBkDC invoke DeleteDC,hMemDC invoke PostQuitMessage,NULL return 0 .endif invoke DefWindowProc,hWin,uMsg,wParam,lParam ret WndProc endp ;Функция для центрирования окна TopXY proc wDim:DWORD, sDim:DWORD shr sDim,1 ;Делим характеристику экрана на 2 shr wDim,1 ;Делим характеристику окна на 2 mov eax,wDim ;Копируем характеристику окна в eax sub sDim,eax ;Вычитаем половину характеристики окна из половины ;характеристики экрана return sDim TopXY endp end start
Файл ресурсов.
#include "c:\masm32\include\resource.h" ///////////////////////////////////////////////////////////////////////////// // Cursor 1000 CURSOR "Cursor.cur" ///////////////////////////////////////////////////////////////////////////// // Menu 2 MENUEX BEGIN POPUP "&Файл", 0x10100,MFT_STRING,MFS_ENABLED BEGIN MENUITEM "В&ыход", 0x10101,MFT_STRING,MFS_ENABLED END POPUP "Правка", 0x10200,MFT_STRING,MFS_ENABLED BEGIN MENUITEM "Очистить", 0x10201,MFT_STRING,MFS_ENABLED END POPUP "Инструменты", 0x10300,MFT_STRING,MFS_ENABLED BEGIN POPUP "Основной цвет", 0x10300,MFT_STRING,MFS_ENABLED BEGIN MENUITEM "Black", 0x10400,MFT_STRING,MFS_ENABLED MENUITEM "Maroon", 0x10401,MFT_STRING,MFS_CHECKED MENUITEM "Green", 0x10402,MFT_STRING,MFS_ENABLED MENUITEM "Olive", 0x10403,MFT_STRING,MFS_ENABLED MENUITEM "Navy", 0x10404,MFT_STRING,MFS_ENABLED MENUITEM "Purple", 0x10405,MFT_STRING,MFS_ENABLED MENUITEM "Teal", 0x10406,MFT_STRING,MFS_ENABLED MENUITEM "Gray", 0x10407,MFT_STRING,MFS_ENABLED MENUITEM "Silver", 0x10408,MFT_STRING,MFS_ENABLED MENUITEM "Red", 0x10409,MFT_STRING,MFS_ENABLED MENUITEM "Lime", 0x1040A,MFT_STRING,MFS_ENABLED MENUITEM "Yellow", 0x1040B,MFT_STRING,MFS_ENABLED MENUITEM "Blue", 0x1040C,MFT_STRING,MFS_ENABLED MENUITEM "Fuchsia", 0x1040D,MFT_STRING,MFS_ENABLED MENUITEM "Aqua", 0x1040E,MFT_STRING,MFS_ENABLED MENUITEM "Light Gray", 0x1040F,MFT_STRING,MFS_ENABLED MENUITEM "Dark Gray", 0x10410,MFT_STRING,MFS_ENABLED MENUITEM "White", 0x10411,MFT_STRING,MFS_ENABLED MENUITEM "Другой...", 0x10412,MFT_STRING,MFS_ENABLED END POPUP "Дополнительный цвет", 0x10300,MFT_STRING,MFS_ENABLED BEGIN MENUITEM "Black", 0x10500,MFT_STRING,MFS_CHECKED MENUITEM "Maroon", 0x10501,MFT_STRING,MFS_ENABLED MENUITEM "Green", 0x10502,MFT_STRING,MFS_ENABLED MENUITEM "Olive", 0x10503,MFT_STRING,MFS_ENABLED MENUITEM "Navy", 0x10504,MFT_STRING,MFS_ENABLED MENUITEM "Purple", 0x10505,MFT_STRING,MFS_ENABLED MENUITEM "Teal", 0x10506,MFT_STRING,MFS_ENABLED MENUITEM "Gray", 0x10507,MFT_STRING,MFS_ENABLED MENUITEM "Silver", 0x10508,MFT_STRING,MFS_ENABLED MENUITEM "Red", 0x10509,MFT_STRING,MFS_ENABLED MENUITEM "Lime", 0x1050A,MFT_STRING,MFS_ENABLED MENUITEM "Yellow", 0x1050B,MFT_STRING,MFS_ENABLED MENUITEM "Blue", 0x1050C,MFT_STRING,MFS_ENABLED MENUITEM "Fuchsia", 0x1050D,MFT_STRING,MFS_ENABLED MENUITEM "Aqua", 0x1050E,MFT_STRING,MFS_ENABLED MENUITEM "Light Gray", 0x1050F,MFT_STRING,MFS_ENABLED MENUITEM "Dark Gray", 0x10510,MFT_STRING,MFS_ENABLED MENUITEM "White", 0x10511,MFT_STRING,MFS_ENABLED MENUITEM "Другой...", 0x10512,MFT_STRING,MFS_ENABLED END POPUP "Толщина линий", 0x10600,MFT_STRING,MFS_ENABLED BEGIN MENUITEM "1 пикс.", 0x10601,MFT_STRING,MFS_ENABLED MENUITEM "2 пикс.", 0x10602,MFT_STRING,MFS_ENABLED MENUITEM "3 пикс.", 0x10603,MFT_STRING,MFS_CHECKED MENUITEM "4 пикс.", 0x10604,MFT_STRING,MFS_ENABLED MENUITEM "5 пикс.", 0x10605,MFT_STRING,MFS_ENABLED END MENUITEM MFT_SEPARATOR MENUITEM "Линия", 0x10301,MFT_STRING,MFS_CHECKED MENUITEM "Эллипс", 0x10302,MFT_STRING,MFS_ENABLED MENUITEM "Контур эллипса", 0x10303,MFT_STRING,MFS_ENABLED MENUITEM "Прямоугольник", 0x10304,MFT_STRING,MFS_ENABLED MENUITEM "Контур прямоугольника", 0x10305,MFT_STRING,MFS_ENABLED END END ///////////////////////////////////////////////////////////////////////////// // Version 1 VERSIONINFO FILEVERSION 1,0,0,1 PRODUCTVERSION 1,0,0,1 FILEFLAGSMASK 0x17L FILEFLAGS 0x1L FILEOS 0x4L FILETYPE 0x0L FILESUBTYPE 0x0L BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "041904b0" BEGIN VALUE "CompanyName", "it.kgsu.ru" VALUE "LegalCopyright", "Copyright (C) 2006" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x419, 1200 END END
Результат работы приложения изображен на рисунке 1:
Рис.1. Результат работы приложения
Данил Алексеевич так прокомментировал свою программу.
Вызываемые функции:
Локальные функции:
Со следующего шага мы начнем рассматривать основы анализа кода программ.