Електронний годинник

Програмна реалізація електронного годинника за допомогою мови програмування асемблер з використанням бібліотек. Структура програми на мові низького рівня. Можливості мов програмування низького рівня і їх незамінність при використанні мікропроцесорів.

Рубрика Программирование, компьютеры и кибернетика
Вид курсовая работа
Язык украинский
Дата добавления 25.03.2011
Размер файла 28,7 K

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

Размещено на http://www.allbest.ru/

Размещено на http://www.allbest.ru/

КУРСОВА РОБОТА

з дисципліни:

«Системне програмування»

на тему:

«Електронний годинник»

Львів 2010

Вступ

Після створення процесора 8086 фірма Intel розробила більш досконалі процесори об'єднані під назвою I 80x86, така назва означає, що всі команди мікропроцесора, які виконуються на молодших моделях обов'язково виконуються на старше, отже все ПЗ, які розроблені для процесора 8086 успішно будуть працювати і на останніх моделях 80486 і Pentium. Ми будемо розглядати процесори з точки зору програміста. Не дивлячись на різноманітність моделей процесорів, найбільш важливим з точки зору біології програмування є 8086 як базова модель і 80386, як перший процесор фірми Intel, який в повному об'ємі реалізував принцип багатозадачності.

Дана курсова робота - це програмна реалізація електронного годинника. Створений за допомогою низької мови програмування асемблер з використанням бібліотек і інк-файлів МАСМ.

1. Програмування на мові асемблера

Програмування на мові асемблера вважається складною задачею, причини цього такі:

Мова асемблера будь-якого процесора суттєво складніша будь-якої мови високого рівня. Щоб скористатись всіма можливостями мови асемблера, треба по крайній мірі знати команди мікропроцесора, а їх число з усіма можливими варіантами переважає 100, їх кількість значно перевищує кількість операторів і ключових слів інших мов високого рівня. Проблема ускладнюється ще тим, що зміни в асемблері виникають набагато швидше ніж в мовах високого рівня, це зв'язано з появою нових мікропроцесорів і відповідно нових команд.

Програміст, який використовує мови асемблера повинен сам слідкувати за розподілом пам'яті та вмістом регістрів, щоб коректно розподіляти і оперувати пам'яттю, в мовах високого рівня це робиться автоматично при допомозі компілятора, але ця обставина має перевагу: можна оптимально розташувати дані в пам'яті, забезпечити максимальну швидкість виконання та мінімальну довжину програми.

Програми на мові асемблера важче проектувати та підлагоджувати, треба весь час пам'ятати, що конкретно знаходиться в кожному регістрів в даній комірці пам'яті. Прийнято вважати, що розробка програми тільки на мові асемблера, деякого процесора, навіть якщо він поширений не рекомендується. Зрозуміло, що будь-яку програму можна написати тільки з допомогою асемблера, але для цього треба використати набагато більшу кількість команд і час який піде на її виконання і відладку буде набагато більший ніж для мови високого рівня. Набагато вигідніше писати програми на мові високого рівня, а найбільш критичні частини на швидкодії писати на мові асемблера. Наприклад на асемблері можна скласти процедури для реалізації вводу-виводу низького рівня, процедури обробки переривань та деякі інші.

Етапи створення програми.

Розробка програми на мові асемблера включає кілька етапів.

Підготовка початкового тексту програми;

Асемблювання програми (отримання об'єктного коду);

Компоновка програми (отримання виконуваного файлу);

Відладка програми (знаходження помилок).

Ці етапи циклічно повторюються.

Підготовка лістінгу програми.

Текст програми на мові асемблера записується в один або кілька файлів, імена файлів і їх розширення можуть бути будь-які, прийнято для файлів які містять програми мовою асемблера прийнято використовувати розширення *.asm. Для файлів визначених констант і повних типів розширення *.inc. Ці файли є текстовими їх можна набрати в будь-якому текстовому редакторі. Можна також використати інтегровані середовища для розробки програм, при програмуванні зручно виділяти один каталог для збереження всіх файлів програми і звідти запускати всі необхідні програми для підготовки, асемблювання та компонування програми. При використанні стандартних редакторів тексту, редаговані тексти треба зберігати у вигляді звичайних файлів у форматі ASCII, це означає, що ці файли треба зберігати без додаткових символів, ці символи часто вставляють в текст різні спеціалізовані редактори, наприклад WORD.

2. Асемблювання програми

Підготовлений текст мови асемблер є початковим для спеціальних програм, які називаються асемблерами, далі програма асемблера. Задача програми асемблера перетворити текст програми у форму двійкових команд, останні можуть вже бути виконанні мікропроцесором. Після асемблювання дістають так звані файли об'єктних модулів, які мають відповідні розширення *.obj. Для отримання об'єктних файлів необхідного виконати відповідну програму асемблера masm фірми Microsoft, або tasm фірми Borland. В обох випадках після команди вказується ім'я файлу: masm prog1.asm, tasm prog1.asm.

Така форма команди є мінімальною, крім цієї форми можна використовувати іншу форму задаючи перед іменем файлу опції або ключі. Якщо програма складається з декількох файлів, то їх асемблювання проводиться незалежно один від одного, хоча отримані об'єктні файли представлені вже в двійковій формі запускати їх на виконання не можливо.

Компоновка програми.

Текст програми може знаходитись в декількох файлах, змінні які описані в цих файлах можуть використовуватися спільно, якщо такі файли асемблюються окремо, то не можливо дістати повну інформацію, для того, щоб генерувати виконавчий код. Тому процес підготовки програми обов'язково включає в себе етап компоновки. На цьому етапі визначають всі невідомі, при окремому асемблювані, адреси всіх змінних або функцій, які використовуються спільно. Процес об'єднання об'єктних модулів в один файл виконується спец. програмою, яка називається компоновщиком. Це може бути програма link фірми Microsoft, або tlink фірми Borland, отримуваний виконуваний файл має розширення *.exe, або *.com. Компановщику треба передати імена відповідних об'єктних файлів.

Link prog1.obj prog2.obj

Tlink prog1.obj prog2.obj

Після компонування отримується виконуваний файл, він отримує ім'я файла, який стоїть перший у відповідній команді.

Відладка програми.

За винятком початкових простих програм практично всі програми на мові асемблера мають потребу в відладці. Для відладки можна використовувати різні відладчики, наприклад tg386-Turbo Debuger фірми Borland. Сучасні відладчики дозволяють в процесі відладки контролювати значення регістрів загального призначення, а також значення змінних і змінювати їх в процесі відладки, можна переглядати зміст різних ділянок пам'яті, можна контролювати виконання покроково, або розставляти точки зупинки.

Використання інтегрованих середовищ (ІС).

Дуже зручно користуватись для підготовки тексту програми редакторами ІС, такі можливості передбачають практично всі виробники сучасних асемблерів. ІС мають суттєву перевагу, так як дають доступ до довідкової інформації. Вони дозволяють також зразу асемблювати та компонувати набрані тексти і провести його відладку. Потім знову можна повернутись до його редагування, при цьому складається ілюзія роботи з однією програмою. Слід відмітити, що відладчики вбудовані в ІС мають дещо обмежені можливості.

3. Структура програми на мові асемблер

Адреси початків сегментів знаходяться у відповідних сегментах регістрах CS, DS, SS, ES - змінюючи вміст цих регістрів можна дістати доступ до тих чи інших ділянок пам'яті, тому такий запис легко зламати. Тому в процесорі 386 в захащеному режимі роботи адреси початків сегментів, їх довжини та права доступу зберігаються в спеціальних системних одиницях. В сегментних регістрах зберігають тільки індекс структури всередині таблиці. Це дозволило ізолювати сегменти та обмежило доступ до них з програми. Адже для доступу потрібно знати не тільки вміст сегменту регістру, але й тієї структури на яку він вказує. Така зміна можлива тільки при використанні привілейованих команд, що виконується тільки в певних умовах, можуть виконуватись в ОС, але не можуть використовуватись в програмах користувача. Паралельно з цим збільшення розміру сегментів:амід 64 Кб для 86, до 4 Гб для 486. Крім того програма буде виконуватись, якщо змінити адресу початку сегменту. Це означає, що в пам'яті він буде перенесений в інше місце. При цьому відносне зміщення в сегменті не можна зміщувати. Це дозволить переносити програму в пам'яті навіть під час її виконання. Використання сегментації пам'яті дозволяє різко збільшити розміри пам'яті, яку можна використати. Так, в захищеному режимі максимально можливий об'єм пам'яті, яку можна адресувати - 64 Тб. Це віртуальна пам'ять. Тоді як фізичний об'єм пам'яті складає 4 Гб. В деяких випадках використовувати сегментацію недоцільно. Тому в старших моделях можна працювати із сегментами довжиною до 4 Гб. Це означає, що вся фізична пам'ять розглядається як один сегмент. Повністю усі переваги сегментації пам'яті проявляється в захищеному режимі роботи. В реальному режимі роботи оперує з 4-ма сегментами: а

Сегмент коду;

Сегмент даних;

Сегмент стеку;

Сегмент додаткових даних.

Для процесорів 386 з'явились ще 2 сегменти додаткових даних. Ці сегменти в пам'яті можуть як завгодно по відношенню один до одного. Ніяких обмежень на їх розташування немає. Сегменти можуть починатись з однієї адреси, тобто можуть перекриватись. Вони можуть в пам'яті без перекривання, або між ними можуть бути проміжки.

Для визначення адреси наступної команди після виконання попередньої використовують 2 регістри: CS (регістр сегменту коду, він містить початок адресу цього сегменту), і IP (регістр вказівника команд, якість зміщення команди відносно початку сегменту). В процесі виконання програми вміст ІР автоматично змінюється. Якщо змінити вміст регістрів CS, та ІР, то виклик програми почнеться з іншої адреси. Але явним чином змінити вміст цих регістрів неможливо. Це можна зробити тільки при використані деяких команд. Наприклад при виклику підпрограми. Або виконані програми безумовного переходу. Як уже відмічалось в сегменті коду можна також описувати дані. Але це роблять тільки в обґрунтованих випадках, наприклад в програмі обробки переривань.

Початок програми.

В початковій версії необхідно було відмітити точку входу в програму деякою міткою. Ім'я цієї мітки потім вказувалось в директиві end. Це було ознакою закінчення файлу з програмою. У сучасних асемблерах для визначення точки входу в програму використовується директива startup. Вона записується в сегменті коду, це спрощує запис і, крім цього, автоматично ініціалізує значення сегментних регістрів. В старих версіях це потрібно було робити вручну.

Кінець програми.

Для закінчення програми потрібно було скористуватись стандартною директивою. Вона робить відповідний виклик автоматично. Якщо програму необхідно закінчити спеціальним чином, наприклад встановити резидентну програму, то користуватись цією директивою не можна. В таких випадках потрібно явно викликати відповідну функцію операційної системи.

Змінні в програмі.

В усіх інших сегментах виділяється місце для змінних, що використовуються в програмі. Поділ сегментів на сегменти даних, стеку та додаткових даних зумовлена тим, що змінні, які тут визначені мають різні властивості. Змінні в програмі можна розбити на 2 великі групи:

Змінні, які явна використовуються в програмі виходячи з її логіки. Такі змінні як правило мають імена і використовуються вони для збереження даних, які мають наперед визначений зміст. Наприклад, змінна що використовується для збереження коду натиснутої клавіші.

Часто в програмі необхідно мати місце для збереження тимчасових даних.

Сегмент даних.

Використовується для збереження змінних, що визначає програміст. Як правило це робиться при допомозі псевдооператорів виділення пам'яті. Для визначення адреси початку сегменту використовується регістр DS. Для визначення другої компоненти адреси (відповідного зміщення всередині сегменту) використовується кілька способів адресації. Зауважимо, що способів визначення адреси змінної набагато більше ніж способів визначення адреси команди. В мові асемблер є засоби для явного розділ. збереження змінних. Ці змінні можуть мати або не мати початкових значень, а також можуть бути змінними константами. Розділяти ці типи змінних не обов'язково. Усіх їх можна зберігати в сегменті даних.

Сегмент стеку використовується для збереження тимчасових даних для яких недоцільно виділяти змінні. Адреса початку цього сегменту розміщується в регістрі SS, а зміщення відносно початку в регістрі SP. Для визначення сегменту стеку використовується директива stack. Цей сегмент відрізняється від сегменту даних і коду. В сегменті даних і коду можна явно адресувати б-я комірку пам'яті. Тут значення регістру при виконанні команд. В кожний момент часу пара цих регістрів SS і SP вказує на так звану вершину стеку. Сюди можна записати або прочитати значення. Стек організований за правилом: перший записаний, останній прочитаний. Тому у програмі команди запису і зчитування зі стеку потрібно використовувати попарно. Стек переважно використовується для тимчасового зберігання адреси повернення з програми або перервань. Завдання стеку - при його допомозі можна передавати аргументи підпрограмам і організовувати локальні змінні.

Формулювання задачі (Призначення пристрою).

Розробка і створення програми яка реалізовуватиме принцип електронного табло (електронний годинник). Дану розробку можна широко застосовувати в повсякденному житті. Зокрема яскравим прикладом є інформаційні табло які широко використовуються на жилізнодорожніх і авто вокзалах та рекламні щити.

Алгоритм розв'язання задачі

Підготовка початкового тексту програми;

Отримання об'єктного коду;

Компоновка програми (отримання виконуваного файлу);

Відладка програми (знаходження помилок).

Ці етапи циклічно повторюються.

Підготовка початкового тексту програми

Текст програми на мові асемблера записав у файл з іменем digclok і розширенням *.asm. Ці файли є текстовими їх можна набрати в будь-якому текстовому редакторі. Можна також використати інтегровані середовища для розробки програм, при програмуванні зручно виділяти один каталог для збереження всіх файлів програми і звідти запускати всі необхідні програми для підготовки, асемблювання та компонування програми.

Отримання об'єктного коду

При перетворенні нашої програми на об'єктний код фактично відбувається переклад програми на двійковий код.

Компоновка програми

Текст програми може знаходитись в декількох файлах, змінні які описані в цих файлах можуть використовуватися спільно, якщо такі файли асемблюються окремо, то не можливо дістати повну інформацію, для того, щоб генерувати виконавчий код. Тому процес підготовки програми обов'язково включає в себе етап компоновки.

Відладка програми

За винятком початкових простих програм практично всі програми на мові асемблера мають потребу в відладці. Для відладки можна використовувати різні відладчики, наприклад tg386-Turbo Debuger фірми Borland. Сучасні відладчики дозволяють в процесі відладки контролювати значення регістрів загального призначення, а також значення змінних і змінювати їх в процесі це роблять тільки в обґрунтованих випадках, наприклад в програмі обробки переривань.

програма електронний годинник асемблер

Висновок

Для сучасного етапу розвитку техніки все більш характерне інтенсивне і глибоке проникнення її в різні галузі мікропроцесорів, які радикально перетворюють властивості багатьох пристроїв і відкривають можливості їх застосування. За широтою та ефективністю використання мікропроцесорів одне з перших місць посідає інформаційно-вимірювальна техніка.

Але окрім технічної реалізації сучасний рівень техніки вимагає і якісної програмної реалізації поставлених завдань. В своїй курсовій роботі я розробив продукт який дозволяє це здійснити. Хоч дана програма є недосконалою і дещо примітивною але на її прикладі яскраво можна продемонструвати можливості мов програмування низького рівня і їхню незамінність при використанні мікропроцесорів.

Список літератури

1. http://www.st.com/stonline/products/literature/pm/4020.pdf

2. http://www.st.com/stonline/products/literature/ds/11381.pdf

3. Зербіно Д.Д. Основи програмування на мікро контролерах.

4. Зербіно Д.Д. Лабораторний практикум.

5. http://www.electrik.org/

6. http://radioded.ru/

Додаток

; Digclock.asm - Цифровий годинник

;-

386

include windows.inc

include user32.inc

include kernel32.inc

include gdi32.inc

includelib user32.lib

includelib kernel32.lib

includelib gdi32.lib

WinMain PROTO:DWORD,:DWORD,:DWORD,:SDWORD

DisplayTime PROTO STDCALL:DWORD,:BOOL,:BOOL

data

ID_TIMER EQU 1

ClassName db «SimpleWinClass», 0

AppName db «Digital Clock», 0

hBrushRed HBRUSH ?

fSuppress BOOL ?

f24Hour BOOL ?

cxClient dd ?

cyClient dd ?

cxC_over2 dd ?

cyC_over2 dd ?

szBuffer db 2 DUP (?), 0 ; zmina nyl byfera

; Bitu vuznachayt iaki z 7 cegmentiv budut cvitutucia z verhy v nuz z liva na pravo

; Po odnomy na kosen bait, bit 6 dlia segmenta 1, bit 5 dlia segmenta 2, 0 dlia 7

Segmt db 01110111b, 00010010b, 01011101b, 01011011b, 00111010b

; 0 1 2 3 4

db 01101011b, 01101111b, 01010010b, 01111111b, 01111011b

; 5 6 7 8 9; 10 chusel

; Vstanovlenia koordunat 6 mist iaki vukor dlia osvitlennia segmentiv

ptSegment POINT {7,6}, {11,2}, {31,2}, {35,6}, {31,10}, {11,10} ; 1 LED segment Verh

POINT {6,7}, {10,11}, {10,31}, {6,35}, {2,31}, {2,11} ; 2 VLivo

POINT {36,7}, {40,11}, {40,31}, {36,35}, {32,31}, {32,11} ; 3 VPravo

POINT {7,36}, {11,32}, {31,32}, {35,36}, {31,40}, {11,40} ; 4 Sereduna

POINT {6,37}, {10,41}, {10,61}, {6,65}, {2,61}, {2,41} ; 5 NLivo

POINT {36,37}, {40,41}, {40,61}, {36,65}, {32,61}, {32,41}; 6 NPravo

POINT {7,66}, {11,62}, {31,62}, {35,66}, {31,70}, {11,70}; 7 Nuz

ptColon POINT {2,21}, {6,17}, {10,21}, {6,25};

POINT {2,51}, {6,47}, {10,51}, {6,55};

data?

hInstance HINSTANCE?

CommandLine LPSTR?

;-

LOWORD MACRO bigword

mov eax, bigword

and eax, 0FFFFh

ENDM

HIWORD MACRO bigword

mov ebx, bigword

shr ebx, 16

ENDM

RGB MACRO red, green, blue

mov al, blue

shl eax, 8

add al, green

shl eax, 8

add al, red

and eax, 0FFFFFFh

ENDM

;-

code

start:

invoke GetModuleHandle, NULL

mov hInstance, eax

invoke GetCommandLine

invoke WinMain, hInstance, NULL, CommandLine, SW_SHOWDEFAULT

invoke ExitProcess, eax

WinMain proc hInst:HINSTANCE, hPrevInst:HINSTANCE, CmdLine:LPSTR, CmdShow:SDWORD

LOCAL wc:WNDCLASSEX

LOCAL msg:MSG

LOCAL hwnd:HWND

mov wc.cbSize, SIZEOF WNDCLASSEX

mov wc.style, CS_HREDRAW or CS_VREDRAW

mov wc.lpfnWndProc, OFFSET WndProc

mov wc.cbClsExtra, NULL

mov wc.cbWndExtra, NULL

push hInstance

pop wc.hInstance

mov wc.hbrBackground, COLOR_WINDOW+1

mov wc.lpszMenuName, NULL

mov wc.lpszClassName, OFFSET ClassName

invoke LoadIcon, NULL, IDI_APPLICATION

mov wc.hIcon, eax

mov wc.hIconSm, 0

invoke LoadCursor, NULL, IDC_ARROW

mov wc.hCursor, eax

invoke RegisterClassEx, addr wc

INVOKE CreateWindowEx, NULL, ADDR ClassName, ADDR AppName,\

WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,\

CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL,\

hInst, NULL

mov hwnd, eax

INVOKE ShowWindow, hwnd, SW_SHOWNORMAL

INVOKE UpdateWindow, hwnd

WHILE TRUE

INVOKE GetMessage, ADDR msg, NULL, 0,0

BREAK.IF (! eax)

INVOKE TranslateMessage, ADDR msg

INVOKE DispatchMessage, ADDR msg

ENDW

mov eax, msg.wParam

ret

WinMain endp

WndProc proc uses ebx esi edi, hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM

LOCAL hdc:HDC

LOCAL ps:PAINTSTRUCT

mov eax, uMsg

IF eax==WM_CREATE

RGB 255,0,0

invoke CreateSolidBrush, eax

mov hBrushRed, eax

invoke SetTimer, hWnd, ID_TIMER, 1000, NULL;

jmp fallth

ELSEIF eax==WM_SETTINGCHANGE

fallth: invoke GetLocaleInfo, LOCALE_USER_DEFAULT, LOCALE_ITIME, ADDR szBuffer, 2

IF szBuffer[0]== «1»

mov f24Hour, TRUE

ELSE

mov f24Hour, FALSE

ENDIF

invoke GetLocaleInfo, LOCALE_USER_DEFAULT, LOCALE_ILZERO, ADDR szBuffer, 2

IF szBuffer[0]== «0»

mov fSuppress, TRUE

ELSE

mov fSuppress, FALSE

ENDIF

invoke InvalidateRect, hWnd, NULL, TRUE

ELSEIF eax==WM_SIZE ; lParam daie novui rozmir vikna

LOWORD lParam

mov cxClient, eax

shr eax, 1

mov cxC_over2, eax

HIWORD lParam

mov cyClient, ebx

shr ebx, 1

mov cyC_over2, ebx

ELSEIF eax==WM_TIMER

invoke InvalidateRect, hWnd, NULL, TRUE

ELSEIF eax==WM_PAINT

invoke BeginPaint, hWnd, ADDR ps

mov hdc, eax

invoke SetMapMode, hdc, MM_ISOTROPIC

invoke SetWindowExtEx, hdc, 276, 72, NULL ; Vctanjv horizontal i vertical stupeniv

invoke SetViewportExtEx, hdc, cxClient, cyClient, NULL

invoke SetWindowOrgEx, hdc, 138, 36, NULL

invoke SetViewportOrgEx, hdc, cxC_over2, cyC_over2, NULL

invoke GetStockObject, NULL_PEN

invoke SelectObject, hdc, eax

invoke SelectObject, hdc, hBrushRed

invoke DisplayTime, hdc, f24Hour, fSuppress ; *** LED display ***

invoke EndPaint, hWnd, ADDR ps

ELSEIF eax==WM_DESTROY

invoke KillTimer, hWnd, ID_TIMER

invoke DeleteObject, hBrushRed

invoke PostQuitMessage, NULL

ELSE

invoke DefWindowProc, hWnd, uMsg, wParam, lParam

ret

ENDIF

xor eax, eax

ret

WndProc endp

DisplayDigit PROC uses ebx esi edi, hdc:DWORD, iNumber:WORD

LOCAL bit:byte

mov bit, 01000000b ; vukor dlia testyvania segmenty masku

mov ebx, 0

mov si, 0 ; Index segment

mov edi, 0

mov di, iNumber ; otrumatu index sufru (0 - 9)

WHILE si < 7

mov cl, bit

test Segmt[di], cl ; Якщо біт маски не встановлено, світлодіодних сегмента OFF

jz skip

invoke Polygon, hdc, ADDR ptSegment[ebx], 6

skip: shr bit, 1 ; Підготовка до наступної тест світлодіодних сегмента

add bx, 8*6 ; індекс до наступного сегменту

inc si

ENDW

ret

DisplayDigit ENDP

DisplayTwoDigits PROC hdc:DWORD, iNumber:WORD, fSuppr:BOOL

mov eax, 0

mov ax, iNumber

mov ecx, 10

mov edx, 0

div ecx ; eax = iNumber/10

IF (! fSuppr || ax!=0)

invoke DisplayDigit, hdc, ax

ENDIF

invoke OffsetWindowOrgEx, hdc, -42, 0, NULL

mov eax, 0

mov ax, iNumber

mov ecx, 10

mov edx, 0

div ecx ; edx = modulus of iNumber/10

invoke DisplayDigit, hdc, dx

invoke OffsetWindowOrgEx, hdc, -42, 0, NULL

ret

DisplayTwoDigits ENDP

DisplayColon PROC hdc:HDC

invoke Polygon, hdc, ADDR ptColon[0], 4

invoke Polygon, hdc, ADDR ptColon [8*4], 4

invoke OffsetWindowOrgEx, hdc, -12, 0, NULL

ret

DisplayColon ENDP

DisplayTime PROC hdc:HDC, f24Hr:BOOL, fSuppr:BOOL

LOCAL syst:SYSTEMTIME

invoke GetLocalTime, ADDR syst

IF f24Hr

invoke DisplayTwoDigits, hdc, syst.wHour, fSuppress

ELSE

mov ax, syst.wHour

mov ecx, 12

mov edx, 0

div cx

IF edx==12

mov ax, syst.wHour

ELSE

mov ax, 12

ENDIF

invoke DisplayTwoDigits, hdc, ax, fSuppr ; Години

ENDIF

invoke DisplayColon, hdc

invoke DisplayTwoDigits, hdc, syst.wMinute, FALSE ; Хвилини

invoke DisplayColon, hdc

invoke DisplayTwoDigits, hdc, syst.wSecond, FALSE ; Секунди

ret

DisplayTime ENDP

end start

Размещено на Allbest.ru


Подобные документы

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.