You are on page 1of 14

Лабораторна робота №2

Тема: Породження процесів та потоків у ОС Windows.


Мета: Навчитись породжувати процеси та потоки у ОС Windows за допомогою
програм на мові Assembler, використовуючи пакет MASM32.

1. Основні теоретичні відомості

1.1 Основні поняття

У деяких аспектах програмування в ОС Windows на асемблері краще ніж


на мовах високого рівня. А саме:
• асемблер дозволяє програмісту повністю контролювати створюваний ним
програмний код;
• компілятори мов високого рівня записують в завантажуваний модуль
програми надлишкову інформацію. Такі ж виконувані модулі, початковий
текст яких написаний на асемблері, мають в декілька разів менший розмір;
• при програмуванні на асемблері зберігається повний доступ до апаратних
ресурсів комп’ютера;
• програма написана на асемблері швидше завантажується в оперативну
пам’ять;
• програма, написана на асемблері, має більшу швидкість роботи і швидше
реагує на дії користувача.
Програмування на асемблері під ОС MS-DOS та під ОС Windows значно
відрізняється. Так DOS програма після запуску повинна бути весь час активною.
Якщо їй що-небудь потрібно, наприклад, дістати наступну порцію даних із
пристрою вводу - виводу, то вона сама має виконувати відповідні запити до
операційної системи. Програма DOS працює по визначеному алгоритмі, вона
завжди знає, що і коли їй треба зробити.
В Windows-програмі все навпаки. Програма є пасивною. Після
завантаження вона чекає коли операційна система виділить їй час. Операційна
система робить це посиланням спеціально оформлених груп даних, які
називаються повідомленнями. Повідомлення можуть бути різного типу, вони
функціонують у системі досить хаотично і прикладна програма не знає якого
типу повідомлення прийде наступним. Можна провести аналогію між
механізмом повідомлень Windows і механізмом переривань в архітектурі IBM
PC.
Слід пам’ятати, що у Windows – програмі перед використанням будь –
якого регістру, крім еах, потрібно зберегти його вміст, який потім треба
відновити.
У процесі розробки своїх програм програміст повинен ефективно
використовувати функції інтерфейсу прикладного програмування API
(Application Programming Interface) операційної системи Windows.
Windows пропонує велику кількість API функцій які розташовані
безпосередньо в операційній системі. Ці функції знаходяться в декількох
динамічно завантажуваних бібліотеках (DLL), таких як kernel32.dll, user32.dll і
gdi32.dll.
Kernel32.dll містить API функції, які взаємодіють з пам’яттю та керують
процесами. User32.dll контролює інтерфейс користувача. Gdi32.dll відповідає за
графічні операції. Крім цих основних бібліотек існують також інші dll, які можна
використовувати, маючи потрібну інформацію про них. Програма динамічно
під’єднується до бібліотеки dll під час виконання, тобто код API функцій не
включається у виконуваний файл. Інформація про функції, які описані в dll
знаходиться в бібліотеках імпорту (*.lib). Windows.inc - містить важливі
структури і константи, які використовуються в програмах. Windows підтримує
два типи прикладних програм:
• віконні прикладні програми - які базуються на основі спеціального набору
функцій (API), які складають графічний інтерфейс користувача GUI (Graphic
User Interface). Віконні прикладні програми являють собою програму, яка весь
вивід на екран представляє у графічному вигляді. Першим результатом
роботи віконної прикладної програми є відображення на екрані спеціального
об’єкта - вікна. Після відображення вікна на екрані вся робота прикладної
програми полягає в тому, щоб підтримувати вікно в актуальному стані;
• не віконні прикладні програми, або консольні програми , являють собою
програми, які працюють у текстовому режимі. Робота консольної програми
нагадує роботу MS-DOS програми. Та це лише із зовнішнього вигляду. У
своєму коді консольна програма використовує функції Windows.
Уся різниця між двома типами прикладних програм Windows полягає в
тому, із яким типом даних вони працюють. Основний тип прикладних програм у
Windows - віконний.
1.2 Створення процесу

При написанні програм іноді виникає потреба у запуску із своєї програми


іншої програми. В середовищі Windows це можна зробити за допомогою функції
CreateProcess (Див. додаток 3). Така програма називається процесом.
Процес - це виконувана прикладна програма, яка складається із власного
віртуального адресного простору, коду, даних та інших ресурсів операційної
системи, таких як файли, папки і синхронізовані об’єкти, видимі для процесу.
Процес має декілька об’єктів: адресний простір, виконуваний модуль чи
модулі, та все, що ці модулі створюють та відкривають. Як мінімум, процес
повинен складатися з виконуваного модуля, власного адресного простору та
потоку. Кожен процес має щонайменше один потік. Потік - це виконувана черга.

2
Коли Windows вперше створює процес, то створюється тільки один потік для
процесу.
1.3 Створення потоку

Коли Windows отримує команду для створення процесу, вона створює


власний адресний простір для процесу, а потім завантажує виконуваний файл у
цей простір. Після цього Windows створює основний потік для процесу.
Потік (thread) – це функція, яка виконується паралельно з батьківською
програмою (програмою, котра створила потік). Потік виконується в тому самому
батьківському процесі, тому він має доступ до всіх ресурсів процесу, глобальних
змінних, дескрипторів і ін. Крім того, кожен потік має свій власний стек (тому
локальні змінні в кожному потоці є приватними), власний набір регістрів (тому
коли Windows завантажує новий потік, то попередній зберігає значення регістрів
і відновлює їх після завершення породженого потоку). Потоки можна розділити
на дві категорії:
1. Потік інтерфейсу користувача: потік такого виду створює своє власне вікно,
тому він отримує віконні повідомлення. Потік може відповідати
користувачеві з допомогою свого власного вікна.
2. Активний потік. Такий тип потоку не створює вікна, тому він не може
приймати повідомлень від Windows. Такий потік існує тільки для того, щоб
виконувати визначене для нього завдання у фоновому режимі.
При використанні великої кількості потоків потрібно створити один потік,
котрий буде займатися інтерфейсом користувача, а інші будуть виконуватись у
фоновому режимі. Так у даному випадку основний потік буде керуючим, а інші
потоки – підлеглими.
Для того щоб створити власний потік потрібно використати функцію
CreateThread (Див. Додаток 5).
Функції CreateProcess і CreateThread завершує кінцева функція
ExitProcess при виході із програми. Якщо існує потреба у знищенні процесу або
потоку не виходячи із програми, то використовують функції TerminateProcess і
TerminateThread. Перевірити чи процес є досі активним (виконується) можна за
допомогою функції GetExitCodeProcess.

2. Хід роботи

1. Ознайомитись з основними теоретичними відомостями даної лабораторної


роботи.
2. Ознайомитись з приведеними в основних теоретичних відомостях
прикладами програм.
3. Ознайомитись з додатковими джерелами, приведеними в п.6 (Література).
4. Затвердити номер індивідуального завдання у викладача.
5. Виконати завдання згідно з номером.

3
3. Зміст звіту Звіт
повинен містити:
- титульну сторінку; - мету роботи;
- завдання, робочий варіант тексту програми, результат виконання
програми;
- короткі висновки по проведеній роботі.

4. Завдання

Скласти на мові асемблер для ОС Windows програму, використовуючи


пакет MASM32. Результат виводиться на екран.

1.Програма повинна виводити повідомлення, яке має містити: Заголовок -


№ групи
Зміст – Ф.І.П Тип –
згідно варіанту:
№ № Тип
1 2 MB_ABORTRETRYIGNORE
3 4 MB_OK
5 6 MB_OKCANCEL
7 8 MB_RETRYCANCEL
9 10 MB_YESNO
11 12 MB_YESNOCANCEL
13 14 MB_ICONEXCLAMATION
15 16 MB_ICONWARNING
17 18 MB_ICONINFORMATION
19 20 MB_ICONASTERISK
21 22 MB_ICONQUESTION
23 24 MB_ICONSTOP
25 26 MB_ICONERROR
27 28 MB_ICONHAND

2.Програма повинна створити процес, котрий повинен:


• Для парних номерів у списку - запустити програму яка виводить
повідомлення (Див. завдання на 60 балів).
• Для непарних номерів у списку – запустити програму згідно варіанту:
№ Програма

4
1 WORD
3 EXCEL
5 ACCESS
7 WORDPAD
9 NONEPAD
11 REGEDIT
13 PAINT
15 CALC
17 FAR
19 IEXPLORE
21 ICHAT
23 WINRAR
25 MSIMN
27 COMMAND.COM
3.
1. Написати програму, яка створює новий процес. Процес повинен
рекурсивно обчислювати факторіал.
2. Написати програму, яка створює новий процес, котрий сортує масив
методом бульбашки.
3. Написати програму, яка створює новий процес, що генерує ряд Фібіоначчі1
з 10-ти членів, використовуючи рекурсивний алгоритм.
4. Написати програму, яка створює новий потік, що сортує слова у стрічці у
алфавітному порядку. Стрічка задається у файлі.
5. Написати програму, яка створює новий процес, котрий сортує слова у
стрічці у порядку збільшення довжини слова. Стрічка задається у файлі.
Відсортована стрічка записується у файл.
6. Написати програму, яка створює новий потік, що рекурсивно обчислює
факторіал.
7. Написати програму, яка створює новий потік. Потік повинен генерувати
ряд Фібіоначчі з 10-ти членів, використовуючи ітераційний алгоритм.
8. Написати програму, яка створює новий потік, котрий сортує слова у
стрічці у порядку зменшення довжини слова. Відсортована стрічка
записується у файл.
9. Написати програму, яка створює новий процес, котрий ітераційно
обчислює факторіал.

1
Ряд Фібіоначчі це така послідовність цифр в якій наступний член рахується як сума двох попередніх.
Наприклад: 0 1 1 2 3 5 8 13 21 34 ...

5
10.Написати програму, яка створює новий процес, котрий сортує масив
методом бульбашки.
11.Написати програму, яка створює новий процес, що генерує ряд випадкових
чисел. Результат записується у файл.
12.Написати програму, яка створює новий потік, котрий ітераційно обчислює
факторіал.
13.Написати програму, яка створює новий процес, що сортує слова у стрічці
у алфавітному порядку. Стрічка задається у файлі.
14.Написати програму, яка створює новий потік, що генерує ряд з 0 і 1 на
основі базису Галуа.
15.Написати програму, яка створює потік, що сортує маcив методом
послідовного перебору.
16.Написати програму, яка створює новий потік, котрий сортує слова у
стрічці у порядку збільшення довжини слова. Стрічка задається у файлі.
Відсортована стрічка записується у файл.
17.Написати програму, яка створює новий процес. Процес повинен
генерувати ряд Фібіоначчі з 10-ти членів, використовуючи ітераційний
алгоритм.
18.Написати програму, яка створює новий потік, котрий сортує масив
методом бульбашки.
19.Написати програму, яка створює новий потік, що генерує ряд Фібіоначчі з
10-ти членів, використовуючи рекурсивний алгоритм.
20.Написати програму, яка створює новий процес, котрий сортує слова у
стрічці у порядку зменшення довжини слова. Відсортована стрічка
записується у файл.
21.Написати програму, яка створює новий процес. Процес повинен
генерувати ряд з 0 і 1 на основі базису Галуа.
22.Написати програму, яка створює новий потік, що генерує ряд випадкових
чисел. Результат записується у файл.

Результати обчислень повинні виводитись на екран, або (згідно завдання)


у файл.

5. Контрольні запитання

1. Переваги програмування в ОС Windows на асемблері?


2. Різниця між асемблерними програмами під ОС MS-DOS та під ОС
Windows?
3. Функції АРІ?
4. Що таке процес?

6
5. Як створити процес?
6. Що таке потік?
7. Як створити потік?
8. Як компонувати та транслювати в MASM32?

Додаток 1
Текст простої програми виводу повідомлення на екран.
.386
.model flat, stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib

.data
MsgCaption db "Повiдомлення!",0
MsgBoxText db "Привiт Win32!",0
.code
start
:
invoke MessageBox, NULL,addr MsgBoxText, addr MsgCaption,
MB_OK invoke ExitProcess,NULL end start

Результат виконання програми:

Опис програми:
.386 – директива, яка говорить асемблеру використовувати набір операцій для
процесора 80386.
MODEL FLAT, STDCALL - .MODEL – директива, яка визначає модель пам’яті
програми. Під WIN32 існує тільки одна модель – плоска. .STDCALL – говорить
асемблеру про порядок передачі параметрів: зліва направо чи справа наліво.
option casemap:none – Робить асемблер чутливим до регістру символів.
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc include
\masm32\include\user32.inc includelib
\masm32\lib\user32.lib includelib \masm32\lib\kernel32.lib
.DATA – В цій частині знаходяться ініціалізовані дані програми.
invoke MessageBox, NULL,addr MsgBoxText, addr MsgCaption, MB_OK -
виклик функції MessageBox, яка виводить діалогове вікно. Параметрами цієї
функції є: дескриптор вікна, адреса тексту, який виведеться у діалоговому вікні,

7
адреса тексту, який виведеться у заголовку діалогового вікна, прапорець.
Прапорець може мати різні значення: MB_ABORTRETRYIGNORE (тоді діалогове
вікно буде мати три кнопки: Abort, Retry і Ignore), MB_OK, MB_OKCANCEL,
MB_RETRYCANCEL, MB_YESNO,MB_YESNOCANCEL і багато інших.
invoke ExitProcess,NULL - Функція завершує всі породжені процеси і потоки.

8
Додаток
2
Текст програми створення процесу.

.386
.model flat,stdcall option
casemap:none
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib

.data
MsgBoxText db "Ця програма запустить новий
процес!",0 MsgCaption db "Повiдомлення!",0
processInfo PROCESS_INFORMATION <> programname db
"Hello.exe",0 startInfo STARTUPINFO <>
.code
main:
invoke MessageBox, NULL,addr MsgBoxText, addr MsgCaption, MB_OK
invoke CreateProcess,ADDR
programname,NULL,NULL,NULL,FALSE,\
NORMAL_PRIORITY_CLASS,\ NULL,NULL,ADDR
startInfo,ADDR processInfo

invoke ExitProcess,NULL end main

Результат виконання програми:

Опис програми :
processInfo PROCESS_INFORMATION <> - Оголошується структура
processInfo, яка має тип структури PROCESS_INFORMATION. Цю структуру
заповнює даними, які містять інформацію про новостворений процес і його
головний потік, функція CreateProcess.
PROCESS_INFORMATION STRUCT
hProcess DWORD ? ;Дескриптор створеного процесу hThread
DWORD ? ;Дескриптор головного потоку створеного процесу
dwProcessId DWORD ? ;Ідентифікатор процесу dwThreadId DWORD ?
;Ідентифікатор основного потоку
PROCESS_INFORMATION ENDS
startInfo STARTUPINFO <> - Оголошується структура startInfo, котра визначає
властивості створеного процесом вікна.
Дескриптор процесу - це значення, яке повертає Windows для використання
іншими АРІ - функціями, зв’язаними з процесами. Дескриптор процесу не може
використовуватися для ідентифікації процесу, так як він не унікальний. Процес
можна примусово зупинити функцією TerminateProcess.

9
Додаток
Додаток 3
Детальний опис функції CreateProcess.
invoke CreateProcess,ADDR programname,NULL,NULL,NULL,FALSE,\
NORMAL_PRIORITY_CLASS,NULL,NULL,\
ADDR startInfo,ADDR processInfo
Функція CreateProcess створює новий процес.
CreateProcess PROTO lpApplicationName:DWORD, lpCommandLine:DWORD,\
lpProcessAttributes:DWORD,lpThreadAttributes:DWORD,
\ bInheritHandles:DWORD,dwCreationFlags:DWORD,\
lpEnvironment:DWORD,lpCurrentDirectory:DWORD,\
lpStartupInfo:DWORD,lpProcessInformation:DWORD

• lpApplicationName --> Вказівник на ім’я виконуваного файлу, з


шляхом або без нього, який потрібно запустити. Якщо цей параметр рівний
NULL, то ім’я виконуваного файлу береться з lpCommandLine.
• lpCommandLine --> Вказівник на командну стрічку в котрій вказаний
шлях до програми, яку потрібно запустити. Якщо lpCommandLine рівний
NULL, то стрічка береться з lpApplicationName.
• lpProcessAttributes і lpThreadAttributes --> Тут вказуються
атрибути безпеки для процесу і основної пам’яті. Коли параметри рівні
NULL, то атрибути безпеки використовуються по замовчуванню.
• bInheritHandles --> Прапорець, який вказує, чи потрібно наслідувати
всі відкриті дескриптори процесу в новому процесі.
• dwCreationFlags --> Декілька прапорців, які визначають поведінку
процесу, який потрібно створити. Наприклад, можна створити процес і
відразу призупинити його виконання, щоб можна було його провірити або
змінити до його виконання. Також можна вказати клас пріоритету потоку
або потоків у новому процесі. Цей клас пріоритету використовується щоб
визначити запланований пріоритет віток всередині процесу. Зазвичай
використовують прапорець NORMAL_PRIORITY_CLASS.
• lpEnviroment --> Вказівник на блок пам’яті, який містить декілька
змінних оточення для нового процесу. Якщо цей параметр рівний NULL, то
новий процес наслідує цей вказівник від батьківського процесу.
• lpCurrentDirectory --> Вказівник на стрічку з поточним диском і
директорією для “дочірнього” процесу. NULL- якщо потрібно, щоб
“дочірній” процес отримав цей вакзівник від батьківського процесу.
• lpStartupInfo --> Вказує на структуру STARTUPINFO, яка визначає як
має з’явитись основне вікно нового процесу. Ця структура містить багато
членів, які виділяють появу головного вікна “дочірнього” процесу. Цю
структуру можна заповнити значеннями батьківського процесу, викликавши
функцію GetStartupInfo.

10
Додаток
• lpProcessInformation --> Вказує на структуру
PROCESS_INFORMATION, яка дістає ідентифікаційну інформацію про новий
процес. Структура
PROCESS_INFORMATION.

4
Текст програми створення потоку
.386
.model flat, stdcall option
casemap:none
include \masm32\include\windows.inc
include
\masm32\include\kernel32.inc
include \masm32\include\user32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
.data?
ThreadID DWORD ?

.data
MsgCaption db "Привiт!",0
MsgBoxText db "В цiй програмi створюється новий потік",0
MsgBoxText2 db "Це повiдомлення нового потоку",0
MsgBoxText3 db "Завершення програми, яка створює новий потік",0

.code

ThreadProc PROC Param:DWORD

invoke MessageBox, NULL,addr MsgBoxText2, addr MsgCaption,


MB_OK ret ThreadProc ENDP
start:

invoke MessageBox, NULL,addr MsgBoxText, addr MsgCaption, MB_OK

mov eax,OFFSET ThreadProc


invoke CreateThread,NULL,NULL,eax, NULL,NORMAL_PRIORITY_CLASS,\
ADDR ThreadID invoke MessageBox, NULL,addr MsgBoxText3, addr
MsgCaption, MB_OK invoke ExitProcess,NULL end start

Результат виконання програми:

11
Додаток
Дана програма виводить повідомлення “Привіт!”, після натиску кнопки
“ОК”, створюється новий потік, котрий виводить своє повідомлення “Привіт!”.
Одночасно з викликом повідомлення потоку викликається повідомлення
батьківської програми (процесу) про завершення програми. Одночасно із
завершенням батьківської програми (після натиску “ОК”) завершується
повідомлення потоку.

12
Додаток
5
Детальний опис функції CreateThread.

invoke CreateThread,NULL,NULL,eax, NULL,NORMAL_PRIORITY_CLASS,\


ADDR ThreadID – Створює новий потік.
CreateThread proto lpThreadAttributes:DWORD,\
dwStackSize:DWORD,\
lpStartAddress:DWORD,\
lpParameter:DWORD,\
dwCreationFlags:DWORD,\
lpThreadId:DWORD

• lpThreadAttributes – Щоб у потоку параметри безпеки


встановлювались по замовчуванню, потрібно використовувати NULL.
• DwStackSize – Вказується розмір стеку. Коли цей параметр
рівний NULL, то потік буде мати такий самий розмір стеку як і у
головного потоку (процесі).
• LpStartAddress – Адреса функції потоку. Ця функція виконує
произначену для потоку роботу. Ця функція повинна одержувати
тільки один 32 – бітний параметр і повертати 32 – бітове значення.
• LpParameter – Параметр, котрий передається функції потоку.
• DwCreationFlags - 0 – означає, що потік починає виконуватися
відразу після його створення. Прапорець CREATE_SUSPEND – загальмує
потік поки не буде викликана функція ResumThread.
• LpThreadId – В цей параметр запишеться ID створеного потоку.

Додаток 6
Опис параметрів командної стрічки.
Для транслювання і компонування даного .ASM файлу ми
використовуємо пакет MASM32. Для того щоб відтранслювати (ML.EXE) та
скомпонувати (злінкувати) (LINK.EXE) даний .ASM код, потрібно вказати в
командній стрічці такі параметри:

ml /c /coff /Cp Hello.asm


link /SUBSYSTEM:WINDOWS /LIBPATH:d:\masm32\lib Hello.obj

Опис параметрів:
/c – говорить MASM’у створити .obj файл формату COFF (Common Object
File), який використовується в ОС UNIX як його власний обєктний і
виконуваний формат файлів.
/Cp – говорить MASM’у зберігати регістр назв, заданих програмістом.
Можна також вставити в код програми (після директиви .model) стрічку

13
Додаток
:option casemap:none, щоб одержати такий самий ефект, тобто, щоб MASM
розрізняв великі і малі символи.
/SUBSYSTEM:WINDOWS – говорить link’еру якого виду буде виконуваний
модуль.
/LIBPATH – говорить link’еру де знаходяться бібліотеки імпорту.
7
Перетворення символів типу int в тип char.
Для того, щоб вивести результати обчислень, потрібно перетворити їх з
типу int в char.Це можна зробити за допомогою функції wsprintf().
.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib
include \masm32\include\user32.inc
includelib \masm32\lib\user32.lib

wsprintfA PROTO C :DWORD, :VARARG


wsprintf equ <wsprintfA>

.data
MsgBoxCaption db "Повідомлення",0
buffer db 50 dup(?)
parametr db "%u",0 ;unsigned int

.co
de
sta
rt:
mov eax,10
add eax,10

invoke wsprintf,addr buffer,addr parametr, eax


invoke MessageBox,NULL,addr buffer, addr
MsgBoxCaption,MB_OK invoke ExitProcess, NULL end
start

Результат виконання програми:

14

You might also like