Міністерство освіти України
Національний університет «Львівська політехніка»
Кафедра автоматизованих систем управління
Розрахункова робота
з дисципліни
"Системне програмування та операційні системи"
на тему:
Годинник, що розмовляє
Зміст
Вступ 4
Огляд літератури 7
Постановка задачі 10
Алгоритм розв’язку задачі 11
Програмні реалізації алгоритму 12
Інструкція користувачеві програми 13
Література 14
Додатки 15
Пояснювальна записка
Вступ
Метою даної курсової роботи є практичне закріплення, поглиблення та розширення знань і вмінь, набутих мною при вивченні дисципліни "Системне програмування та операційні системи"
Тема моєї курсової роботи – Годинник, що розмовляє
Win32 API (розшифровується як інтерфейс прикладних програм) - це множина підпрограм-функцій, на яких побудована операційна система WINDOWS, яка використовує 32х-бітну адресацію, починаючи з WINDOWS 95 і закінчуючи WINDOWS XP. Розробники WINDOWS зробили багато зусиль щоб стандартизувати як назви функцій, так і їх параметри. Тому використовувати їх не так важко, якщо засвоїти деякі загальні концепції.
Більшість функцій доступні для програм користувача, які написані для Windows на будь-якій мові програмування (у тому числі і на асемблері). Множина цих функцій розширюється при переході до наступної версії Windows, таким чином, забезпечується сумісність розроблених раніше програм із новими версіями операційної системи. Існують і функції, які не відображені в документації, або для свого застосування вимагають від програми спеціальних прав доступу до пам’яті.
Суть функцій API зрозуміти значно легше, якщо уявити, з яких файлів вони викликаються і на які групи ці функції поділяються. Асемблер – це як раз той зручний і простий засіб, який дозволить вам звертатись безпосередньо до будь-якої функції API, що знаходиться у DLL(файлі.
Секрет пізнання операційної системи через програмування на асемблері полягає у тому, що сам асемблер не накладає жодних обмежень на програму та дані, з якими вона працює. Це повинен робити сам програміст з метою захисту операційної системи від своїх некоректних дій. Таким чином, основною метою системного програмування є написання коректних програм з необмеженими можливостями (в рамках операційної системи). Для збереження коректності ми будемо користуватися певними правилами програмування, які будуть зрозумілі на конкретних прикладах.
Типи програм. Процесори стандарту Intel можуть працювати в трьох основних режимах: реальному, віртуальному і захищеному. При включенні комп’ютера його процесор працює в реальному режимі. Після завантаження операційної системи (ОС) процесор може бути переключений програмами ОС в інші режими. В реальному та віртуальному режимах використовується 16-бітна адресація з фіксованими сегментами по 64К. У захищеному режимі використовується 32х-бітна адресація з необмеженими сегментами, і адреса до пам’яті формується (на апаратному рівні) за допомогою дескрипторних таблиць, в яких задаються початкові адреси сегментів, їх довжина, та права доступу до пам'яті і до портів для процесів, які їх використовують. Крім того, в захищеному режимі реалізоване апаратне переключення між задачами за допомогою спеціальних таблиць.
Особливості виклику функцій API. Найбільш перспективним з точки зору програмування є захищений режим, тому що він використовує всі апаратні можливості комп’ютера. Отже, функції API для Windows відіграють ту ж саму роль, що і переривання INT 21h для DOS в реальному або віртуальному режимі, але, відмінності між ними досить суттєві. Перелічимо їх:
Функції API не відміняють, а заміняють програмні переривання. Механізм обробки апаратних переривань залишається на рівні драйверів пристроїв;
Стандарт виклику функцій API оснований на передачі параметрів через стек (а не через регістри);
Значення кожної функції повертається в регістрі EAX. Якщо функція повертає структуру даних, то регістр EAX містить логічну ознаку виконання, а адресу структури необхідно передати до функції як параметр;
Функції API працюють у захищеному режимі процесора, а переривання DOS ( у реальному чи віртуальному режимі.
Функції API зберігаються у різних бібліотеках динамічного компонування, які знаходяться у файлах із розширенням DLL, наприклад, kernel32.dll, user32.dll, gdi32.dll та ін. Ці файли знаходяться у системному каталозі Windows (наприклад, “C:\Windows\System”). У разі необхідності, програміст може створити DLL(файл з набором своїх функцій.
Програми Windows звертаються до функцій API за допомогою команд апаратного виклику CALL, наприклад: call MessageBoxA, де MessageBoxA – 32х-бітна адреса функції. Саме ця назва функції фігурує у файлі user32.dll (подивіться редактором цей файл). Перелік можливих функцій є у файлі H:/tasm/lib/Import32.lib, який називається бібліотекою імпорту.
Параметри для виконання будь-якої функції API перед її викликом повинні засилатися в стек, починаючи з останнього параметра (див. текст програми). Тому кожний параметр є 32х-бітним числом (в якому можуть використовуватись не всі біти). Параметрами досить часто бувають спеціальні дескриптори ( хендли (HANDLE) та атоми.
Дескриптори (хендли та атоми) – це унікальні цілі числа, які Windows використовує для ідентифікації об’єктів, які створюються або використовуються в системі. Хендли займають по 4 байти, а атоми – по 2 байти. Хендли ідентифікують вікна, меню, блоки пам’яті, екземпляри програми, пристрої виводу, файли, аудіо та відео потоки, та інші об’єкти. Атоми ідентифікують стандартні іконки, курсори та об’єкти, які не змінюються при наступному завантаженні системи.
Більшість дескрипторів є значеннями індексів внутрішніх таблиць, які Windows використовує для доступу та керування своїми об’єктами. Звичайно, програми користувача (ужитки) в захищеному режимі не мають прав доступу до цих таблиць. Тому, коли необхідно отримати чи змінити дані, що пов’язані з певним об’єктом Windows, ужиток використовує відповідну функцію API з параметром хендла цього об’єкту. Таким чином Windows забезпечує захист своїх даних при роботі у багатозадачному режимі.
1. Огляд літератури
Оглянувши багато літератури, можна сказати, що існує безліч методів для вирішення даної задачі. Всі методи мають свої алгоритми, які можуть бути складними, або простішими, але все зводиться до одного – створення годинника, що розмовляє.
Ідея технології ActiveX полягає в тому, щоб зв’язати WEB-технологію з компонентами, які встановлені на комп’ютері у користувача. Таким чином, компонент може бути активізований і керуватися через WEB-сторінки, якщо в них є посилання на ці об’єкти. Другий варіант ActiveX – це можливість керування компонентом з віддаленого WEB-сервера, або робота компонента під управлінням цього сервера.
Технологія ActiveX побудована на методах OLE і використовує стандартні функції реєстрації та створення COM-об’єктів. Для роботи з COM-об’єктом необхідно створити екземпляр його інтерфейсу за допомогою API функції CoCreateInstance. Після створення екземпляру об’єкту (інтерфейсу) його необхідно відповідним чином ініціалізувати. Уникнути ініціалізації можна, якщо створювати екземпляр інтерфейсу більш спеціалізованими функціями (наприклад, функцією OleLoadPicture для інтерфейсу IPicture).
В даній роботі розглядається керування одним з таких об’єктів як Microsoft Agent. Цей компонент був створений для підтримки дружнього інтерфейсу з користувачем і виглядає як казковий персонаж, що керується певними командами. Компоненти Microsoft Agent входять в склад операційних систем Windows, починаючи з версії 2000. На інші системи ці компоненти можна інсталювати з сервера фірми Microsoft. Персонажі можуть виглядати по-різному, але всі вони підтримують один стандартний набір команд.
Технологія ActiveX не залежить ні від мови програмування, ні від платформи; тому її можна віднести до одної з технологій системного програмування.
Оскільки керуючі елементи ActiveX можуть виконувати в системі клієнта довільні дії, то не можна допускати, щоб WEB-клієнт міг загрузити довільний об’єкт ActiveX. Ці компоненти можна лише завантажувати з сервера Microsoft.
Якщо проглянути текст програми, то можна побачити застосування наступних методів до активізованого об’єкта “Microsoft agent”: MoveTo, Play, Speak. На низькому рівні методи організовані як таблиця з адресами підпрограм, які їх реалізовують. У таблиці 1 подані символічні назви методів, їх адреси, кількість параметрів. Назва методів та їх порядок у таблиці подаються в довідкових файлах *.h, які додаються до компілятора С++.
Таблиця 1
№
Адреса в Таблиці
Назва методу
Параметри
Зміст параметрів
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
0h
04h
08h
0Ch
10h
14h
18h
1Ch
20h
24h
28h
2Ch
30h
34h
38h
3Ch
40h
44h
48h
4Ch
50h
54h
58hl
5Ch
60h
64h
68h
6Ch
70h
74h
78h
7Ch
80h
84h
88h
8Ch
90h
94h
98h
9Ch
0A0h
0A4h
0A8h
0ACh
0B0h
0B4h
0B8h
0BCh
0C0h
0C4h
0C8h
0CCh
0D0h
0D4h
0D8h
0DCh
0E0h
0E4h
0E8h
0Ech
0F0h
QueryInterface
AddRef
Release
GetTypeInfoCount
GetTypeInfo
GetIDsOfNames
Invoke
GetVisible
SetPosition
GetPosition
SetSize
GetSize
GetName
GetDescription
GetTTSSpeed
GetTTSPitch
Activate
SetIdleOn
GetIdleOn
Prepare
Play
Stop
StopAll
Wait
Interrupt
Show
Hide
Speak
MoveTo
GestureAt
GetMoveCause
GetVisibilityCause
HasOtherClients
SetSoundEffectsOn
GetSoundEffectsOn
SetName
SetDescription
GetExtraData
ShowPopupMenu
SetAutoPopupMenu
GetAutoPopupMenu
GetHelpFileName
SetHelpFileName
SetHelpModeOn
GetHelpModeOn
SetHelpContextID
GetHelpContextID
GetActive
Listen
SetLanguageID
GetLanguageID
GetTTSModeID
SetTTSModeID
GetSRModeID
SetSRModeID
GetGUID
GetOriginalSize
Think
GetVersion
GetAnimationNames
GetSRStatus
in, out
-
-
out
in, in, out
in, in, in, in, out
in,in,in,in,i/o,out
out
in, in
out, out
in, in
out, out
out
out
out
out
in
in
out
in, in, in, out
in, out
in
in
in, out
in, out
in, out
in, out
in, in, out
in, in, in, out
in, in, out
out
out
out
in
out
in
in
out
in, in
in
out
out
in
in
out
in
out
out
in
in
out
out
in
out
in
out
out, out
in, out
out, out
out
out
Адр. ідентиф., Адр.хендлу
-
-
Адр. буферу
Тип, ID, Адр. буферу
IID, Size, Name, ID, Адр. буф.
ID,IID,ID,Flg,Адр.буф,Адр.буф
Адреса ідентифікатора
Координати X,Y
Адреса координат X,Y
Ширина, висота
Адреса ширини, висоти
Адреса буферу
Адреса буферу
Адреса змінної
Адреса змінної
Значення початкового стану
Значення-прапорець
Адреса змінної
Тип, Ім’я, Черга, Адр. ідентиф.
Адреса буферу, Адр. ідентифік.
Ідентифікатор
Тип дії
Ідентифікатор, Адр. ідентифік.
Ідентифікатор, Адр. ідентифік.
Швидкість, Адр. ідентифік.
Швидкість, Адр. ідентифік.
Адр.тексту, Адр.файлу, Адр.ID.
X, Y, Швидкість, Адр. ідентиф.
X, Y, Адр. ідентифік.
Адреса буферу
Адреса буферу
Адреса змінної
Значення-прапорець
Адреса змінної
Адреса буферу
Адреса буферу
Адреса буферу
X, Y
Прапорець
Адреса прапорця
Адреса імені
Адреса імені
Прапорець
Адреса прапорця
Адреса IID
Адреса рядка
Адреса прапорця
Прапорець
Ідентифікатор
Адр. Ідентифікатора
Адреса рядка
Адр. Ідентифікатора
Адреса рядка
Адреса рядка
Адреса рядка
Адреса X, Адреса Y
Адр. рядка, Адр. ідентиф.
Адр. ідентиф., Адр. ідентиф.
Адреса буферу
Адреса прапорця
Для виклику довільного методу використовується три команди асемблера:
mov edx, хендл інтерфейсу об’єкта
mov edx, [edx]
call [edx+ адреса метода в таблиці], хендл інтерфейсу об’єкта, параметри
Кожна таблиця методів містить на початку стандартні спеціалізовані методи QueryInterface, AddRef, Release, які будуть розглянуті в роботі.
Для деяких методів (наприклад, Speak) необхідно виділяти системну область пам’яті. Пам’ять з програми користувача для них не підходить. Для цього існує функція SysAllocString, яка резервує фрагмент системної пам’яті і одразу ж копіює в нього рядок з пам’яті користувача, який закінчується двома нулями (див. далі текст програми). Після використання цей фрагмент знищується за допомогою функції SysFreeString, параметром якої є адреса цього фрагменту.
Всі керуючі дії для об’єктів ActiveX (так само як і для об’єктів мережі) необхідно передавати в юнікодах. Для перетворення рядка в юнікод в програмі використана функція MultiByteToWideChar.
Принцип взаємодії комп’ютера з будь-яким зовнішнім пристроєм оснований на використанні переривань. Якщо в пристрої відбувається певна подія, то він видає запит на переривання. Це зроблено для збереження часу центрального процесора. Якщо в операційній системі задіяний пристрій, який не використовує переривань, то програма користувача, яка працює з цим пристроєм вимушена робити полінг, тобто, періодично опитувати пристрій на предмет того, чи не сталася в ньому будь-яка подія (наприклад, якщо в пристрій надійшли дані).
Система переривань дозволяє звернути увагу процесора на пристрій саме в той момент, коли це потрібно, тобто тоді, коли в ньому починає відбуватися певна подія. Такий принцип активізації процедури через контролер переривань і покладений в основу набору функцій API і методів DirectSound, якими користується програміст при взаємодії зі звуковою картою.
Отже, звукова карта являє собою спеціалізований комп’ютер для відтворення та прийому звукових сигналів. Вона має локальну пам’ять і спеціалізований процесор, тому програвання або прийом звуку відбувається паралельно з роботою інших програм. Коли закінчується програвання (або прийом) звукового фрагменту, який знаходиться в її локальній пам’яті, вона видає запит на переривання, після чого програма обробки переривань повинна “підкачати” наступний фрагмент у локальну пам’ять карти (або забрати його з її локальної пам’яті).
Ввід звукових даних складається з наступних кроків:
waveInOpen – відкриває звуковий пристрій для вводу інформації. Результатом виклику цієї функції є хендл відкритого пристрою: змінна WaveIn (див. програму далі). Перед відкриттям пристрою його властивості необхідно описати в структурі WAVEFORMATEX, де вказати кількість каналів, частоту дискретизації та розрядність аналого-цифрового перетворювача.
waveInPrepareHeader – готує робочий заголовок буферу, який описує аудіо-дані. Параметрами цієї функції є хендл відкритого аудіо-пристрою, адреса структури WAVEHDR, в якій вказана адреса поточного буферу, адреса наступного заголовку та його довжина. Структура WAVEHDR містить одночасно вхідні і вихідні параметри. Вихідною змінною є наприклад, кількість байт даних, що передані з пристрою в буфер.
waveInAddBuffer – додає буфер для вводу даних, що описаний в попередній функції. Дану функцію треба виконувати щоразу після заповнення попереднього буферу.
4. waveInStart – розпочинає процес заповнення буферу. Як тільки буфер заповниться, то викликається callback-процедура, адреса якої вказується в параметрах функції waveInOpen
2. Постановка задачі
Порграма повинна містити в собі аналоговий годинник, що працює. Також оголошувати годину кожної хвилини. Годинина, ще оголошується при натисканні на клавішу пробіл. У даній задачі використовую файли ресурсів. Зокрема це застосовується для виведення самого зображення годинника. Використовується файл ресурсів для надання програмі іконки.
Ресурсні дані включаються в програмний модуль як окрема секція даних, яка завантажується в оперативну пам’ять по частинах по мірі необхідності за допомогою функцій LoadBitmapA, LoadIconA, Для включення певних даних у виконуючий файл їх необхідно описати у спеціальному текстовому файлі з таким самим іменем та розширенням “.rc”. Цей файл складається з окремих рядків, кожний з яких описує фрагмент ресурсних даних, які після компіляції будуть включені exe-модуль.. Ключове слово ICON вказує на тип ресурсних даних, які будуть приєднані до exe-модуля. Name1 – це внутрішній ідентифікатор, по якому можна буде знайти вказані дані в секції ресурсів. Результатом компіляції RC-файлу CLOCK1.RC завжди буде RES-файл CLOCK1.RES. Файл CLOCK1..RES буде використаний для лінкування модуля
Для розв’язання даної задачі мені необхідно було здійснювати різноманітні математичні підрахунки, які реалізувати можна за допомогою сопроцесора ( .387 ).
Також необхідною річчю є використання технології ActiveX. Саме за допомогою цієї технології і здійснюється проголошення поточного часу. Вимовляння здійснюється з використанням трьох різних, але водночас однакових за будовою масивів.
3. Алгоритм розв’язку задачі
В даній курсовій роботі:
- насамперед оголошуємо функції, що будуть використовуватись;
-константи, які необхідні для виконання функцій;
- оголошую необхідні змінні
В тілі програми:
- визначаємо поточний час, дату, рік, місяць, день
- після цього визначаємо початкове місцезнаходження годинникових стрілок
- створюємо вікно
- Завантажуємо іконку та фон (картинку аналогового годинника)
- Підготовляємо необхідні компоненти ActiveX, де безпосередньо відбувається оголошення часу
- Запускаємо таймер
- Слідкуємо за натиснутими клавішами та опрацьовуємо їх(цикл прийому повідомлень
-процедури для переміщення стрілок
-процедури для оголошення часу
--завершення програми.
4. Програмні реалізації алгоритму.
Опис програмного комплексу на мові Assembler.
Загальна характеристика програми:
Ім’я програми – clock1
Назва файлів – clock1.asm
clock1.rc
clock1.res
clock1.exe
face03.ico
Ris.bmp
Мова програмування – Assembler.
Об’єм програми – текстових рядків або байт –20 кБ (969 рядків).
Призначення програми:
Ця програма призначена для виводу на екран часу та його озвучення.
Вхідна інформація:
Вхідна інформація не вводиться,
Вихідна інформація:
Виводиться у вигляді аналогового годинника, да за допомогою звуку
5. Інструкція користувачеві програми.
Запустити файл програми.
Подивитись результати на екрані та прослухати звукову інформаціюЛітература
Методичні вказівки з курсу “Сиcтемне програмування та операційні системи” для студентів базової вищої освіти за напрямком 6.08.04 “Комп’ютерні науки”.
ASSEMBLER & WIN32, Александр Усов(електронний варіант)
Всесвітня мережа Інтернет
електронний довідник WIN32.hlp
По заказу Центрального института повышения квалификации руководящих работников и специалистов черной металлургии. Разработчики: к.т.н., доц. ТЕР-АКОПОВ Р.С., АЛЕКСЕЕВ А.А. Научный руководитель проекта: к.т.н., доцент Гладков А.И.
Додатки.
Додаток №1
Текст програми на мові Assembler.
.386
.387
model flat, STDCALL
extrn ExitProcess: proc
extrn DispatchMessageA: proc
extrn DefWindowProcA: proc
extrn CreateWindowExA: proc
extrn GetModuleHandleA: proc
extrn Ellipse: proc
extrn LineTo: proc
extrn MoveToEx: proc
extrn SetTimer: proc
extrn GetMessageA: proc
extrn GetDC: proc
extrn GetLocalTime: proc
extrn ReleaseDC:proc
extrn SetROP2:proc
extrn MessageBoxA:proc
extrn _wsprintfA:Proc
extrn CoInitialize:Proc
extrn CoCreateInstance:Proc
extrn MultiByteToWideChar:Proc
extrn SysAllocString:Proc
extrn SysFreeString:Proc
extrn GetModuleHandleA:Proc
extrn LoadIconA:Proc
extrn LoadBitmapA:Proc
extrn TranslateMessage:Proc
extrn InitCommonControls:Proc
extrn SendMessageA:Proc
WS_POUP equ 80000000h
WS_VISIBLE equ 10000000h
R2_NOTXORPEN equ 10
WM_KEYDOWN equ 100h
VK_SPACE equ 20h
SS_BITMAP equ 0Eh
STM_SETIMAGE equ 172h
IMAGE_BITMAP equ 0
.data
Time_title db ' Говорячий годинник. Поточні час і дата',0
TIME_STRING db 2000 dup (0)
FORMAT_STRING:
db ' Системний час:',0dh,0ah,0dh,0ah
db ' Рiк: %ld',0dh,0ah
db ' Мiсяць: %ld',0dh,0ah
db ' День тижня: %ld',0dh,0ah
db ' Число: %ld',0dh,0ah
db ' Година: %ld',0dh,0ah
db ' Хвилин: %ld',0dh,0ah
db ' секунд:%ld',0dh,0ah
db 0
Time_struc:
wYear dw 0 ; Рік
wMonth dw 0 ; Місяць
wDayOfWeek dw 0 ; День тиждня
wDay dw 0 ; Число
wHour dw 0 ; Година
wMinute dw 0 ; Хвилина
wSecond dw 0 ; Секунда
wMilliseconds dw 0 ; Мілісекунда
hwnd dd ?
hdc dd ?
;===================================Для секунд============================================
x0 dd 96.
y0 dd 92.
x1 dd 96.
y1 dd 30.
x2 dd 0.
y2 dd 0.
x0z dd 96
y0z dd 92
x1z dd 96
y1z dd 30
x2z dd 0
y2z dd 0
;=====================================Для хвилин===========================================
x02 dd 96.
y02 dd 92.
x12 dd 96.
y12 dd 40.
x22 dd 0.
y22 dd 0.
x0z2 dd 96
y0z2 dd 92
x1z2 dd 96
y1z2 dd 40
x2z2 dd 0
y2z2 dd 0
;====================================Для годин===============================================
x03 dd 96.
y03 dd 92.
x13 dd 100.
y13 dd 50.
x23 dd 0.
y23 dd 0.
x0z3 dd 96
y0z3 dd 92
x1z3 dd 100
y1z3 dd 50
x2z3 dd 0
y2z3 dd 0
;======================================Для розмови====================================================
IID_IAgentEx dd 48d12ba0h
dw 5b77h,11d1h
db 9Eh,0C1h, 00h,0C0h,4Fh,0D7h,08h,1Fh
Size1 dd 0
Size2 dd 0
x dd 0
y dd 0
TITLE1 db "Виконує дiю:",0
SAYS_0:
db "0 hour",0
db "1 hour",0
db "2 hour",0
db "3 hour",0
db "4 hour",0
db "5 hour",0
db "6 hour",0
db "7 hour",0
db "8 hour",0
db "9 hour",0
db "10 hour",0
db "11 hour",0
db "12 hour",0
db "13 hour",0
db "14 hour",0
db "15 hour",0
db "16 hour",0
db "17 hour",0
db "18 hour",0
db "19 hour",0
db "20 hour",0
db "21 hour",0
db "22 hour",0
db "23 hour",0
end_SAYS_0 db 0
SAYS1:
db "0 minut",0
db "1 minut",0
db "2 minut",0
db "3 minut",0
db "4 minut",0
db "5 minut",0
db "6 minut",0
db "7 minut",0
db "8 minut",0
db "9 minut",0
db "10 minut",0
db "11 minut",0
db "12 minut",0
db "13 minut",0
db "14 minut",0
db "15 minut",0
db "16 minut",0
db "17 minut",0
db "18 minut",0
db "19 minut",0
db "20 minut",0
db "21 minut",0
db "22 minut",0
db "23 minut",0
db "24 minut",0
db "25 minut",0
db "26 minut",0
db "27 minut" ,0
db "28 minut",0
db "29 minut",0
db "30 minut",0
db "31 minut",0
db "32 minut",0
db "33 minut",0
db "34 minut",0
db "35 minut",0
db "36 minut",0
db "37 minut",0
db "38 minut",0
db "39 minut",0
db "40 minut",0
db "41 minut",0
db "42 minut",0
db "43 minut",0
db "44 minut",0
db "45 minut",0
db "46 minut",0
db "47 minut",0
db "48 minut",0
db "48 minut",0
db "49 minut",0
db "50 minut",0
db "51 minut ",0
db "52 minut",0
db "53 minut",0
db "54 minut",0
db "55 minut",0
db "56 minut",0
db "57 minut",0
db "58 minut",0
db "59 minut",0
end_SAYS1 db 0
SAYS2:
db "0 second",0
db "1 second",0
db "2 second",0
db "3 second",0
db "4 second",0
db "5 second",0
db "6 second",0
db "7 second",0
db "8 second",0
db "9 second",0
db "10 second",0
db "11 second",0
db "12 second",0
db "13 second",0
db "14 second",0
db "15 second",0
db "16 second",0
db "17 second",0
db "18 second",0
db "19 second",0
db "20 second",0
db "21 second",0
db "22 second",0
db "23 second",0
db "24 second",0
db "25 second",0
db "26 second",0
db "27 second",0
db "28 second",0
db "29 second",0
db "30 second",0
db "31 second",0
db "32 second",0
db "33 second",0
db "34 second",0
db "35 second",0
db "36 second",0
db "37 second",0
db "38 second",0
db "39 second",0
db "40 second",0
db "41 second",0
db "42 second",0
db "43 second",0
db "44 second",0
db "45 second",0
db "46 second",0
db "47 second",0
db "48 second",0
db "48 second",0
db "49 second",0
db "50 second",0
db "51 second",0
db "52 second",0
db "53 second",0
db "54 second",0
db "55 second",0
db "56 second",0
db "57 second",0
db "58 second",0
db "59 second",0
end_SAYS2 db 0
MSG: ; Структура стандартного повідомлення WINDOWS
msHWND dd 0 ; хто надіслав
msMESSAGE dd 0 ; яку інформацію
msWPARAM dd 0 ; про що
msLPARAM dd 0 ; і як
msTIME dd 0 ; коли
ptX dd 0 ; де (X),
ptY dd 0 ; (Y)
hAgent dd 0
hAgentObject dd 0
vPath dd 0
IChrID dd 0
IReqID dd 0
hAgentChar dd 0
Var1 dd 0
ADR1 dd 0
BUF1 db "Dobrogo dnya",0
Index dd 0
BUF2 dw 1000 dup(0)
Name1 db "face",0
Name2 db "Back",0
HDC dd 0
CLSID_AgentServer dd 0d45fd2fch
dw 5c6eh, 11d1h
db 9Eh,0C1h, 00h, 0C0h,4Fh,0D7h,08h,1Fh
;==========================================Кути стрілок====================================================
a dd 0.104719755119
a1 dd 0.00174532925
a3 dd 0.000048481368
alfa dd 0.0
second dd 0.0
minute dd 0.0
hour dd 0.0
dil dd 60
h dd 5
;=========================================Інші змінні============================================================
cn db 'Static',0
msg dd 7 dup( 0 )
f db 0
f2 db 0
f3 db 0
lichulnukS dd 0
lichulnukM dd 0
lichulnukH dd 0
Hbmp dd 0
.code
Start:
;=====================================Поточний час ======================================================
push offset Time_struc
call GetLocalTime
xor eax,eax
mov ax,wSecond
push eax
mov ax,wSecond
push eax
mov