МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ
НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ “ЛЬВІВСЬКА ПОЛІТЕХНІКА”
ЗВІТ
З лабораторної роботи №5
з дисципліни “Системне програмування”
на тему: “ Особливості програмування з використанням функцій Win32 API”
Мета: ознайомитись з можливостями та набути навиків програмування на Асемблері в OS Windows та засвоїти навики використання функцій API Win32.
ЗАВДАННЯ
Реалізувати програму, що викликає Win32 API функцію згідно варіанту і виводить результат її роботи на екран.
№ варіанту
Функція API
27
GetSystemTime
ХІД ВИКОНАННЯ
Згідно варіанту змінюю код програми наведеної в методичних вказівках на власний.
Лістинг програми
.586 ; для процесора не нижче INTEL-586
.model flat, STDCALL ; компілювати як програму для WIN32
option casemap :none ; код чутливий до регістру літер
; Визначення зовнішніх процедур:
include \masm32\include\windows.inc ; завжди першим
include \masm32\macros\macros.asm ; підтримка макросів MASM
; --------------------------------------------------------------
; підключення файлів з форматами прототипів виклику функцій
include \masm32\include\masm32.inc
include \masm32\include\gdi32.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
; --------------------------------------------------------------
; підключення заголовків бібліотек експортованих функцій
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
.DATA
TIME SYSTEMTIME<>
TIMEFORMAT db "HH:mm:ss",0
;my_title db ' Лабораторна робота № 5 ', 0
;my_message db 'Time is: ' ;
szBuffer db 100 dup (0)
.CODE
start:
invoke GetSystemTime,offset TIME
invoke GetTimeFormat,LOCALE_USER_DEFAULT,NULL,offset TIME, offset TIMEFORMAT, offset szBuffer, sizeof szBuffer
invoke MessageBox,0,offset szBuffer,0,MB_OK
invoke ExitProcess,0
END start
Результат виконання нової програми
/
Рисунок 1. Результат виконання нової програми
Висновок: на даній лабораторній роботі я ознайомився з можливостями та набув навиків програмування на Асемблері в OS Windows та засвоїв навики використання функцій API Win32.
4.2.1
; Program "Hello world"
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
; ПРОЦ, МОДЕЛЬ, ОПЦІЇ, ІНКЛУДИ, БІБЛІОТЕКИ ІМПОРТУ
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
.386
.model flat, stdcall
option casemap:none
;includelib libcmt.lib; for new vs(from vs2015)
;includelib libvcruntime.lib; for new vs(from vs2015)
;includelib libucrt.lib; for new vs(from vs2015)
;includelib legacy_stdio_definitions.lib; for new vs(from vs2015)
includelib msvcrt.lib; for old vs(to vs2013)
;includelib masm32\lib\msvcrt.lib; for masm32p
;includelib \masm32\lib\msvcrt.lib; for masm32
includelib kernel32.lib; for vs
;includelib masm32\lib\kernel32.lib; for masm32p
;includelib \masm32\lib\kernel32.lib; for masm32
SetConsoleTitleA PROTO :DWORD
GetStdHandle PROTO :DWORD
WriteConsoleA PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD
ExitProcess PROTO :DWORD
Sleep PROTO :DWORD
sprintf PROTO near C :DWORD,:VARARG
strlen PROTO near C :DWORD
.data
sWriteText db 'HELLO, WORLD!!!!', 128 dup(0)
fmt db "result = %.3lf", 13, 10, 0;
temp qword ?
;// X= A2*B1+C1/ (K-E1*F1)
vA dq 10.; +8
vB dd 20.; +16
vC dd 30.; +20
vE dd 40.; +24
vF dd 50.; +28
a dq 10., 20., 30.;
x dq ?, ?, ?;
K equ 1; (153136d)
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
; СЕКЦІЯ КОНСТАНТ
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
.const
sConsoleTitle db 'My First Console Application',0
;sWriteText db 'HELLO, WORLD!!!!', 128 dup(0)
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
; СЕКЦІЯ КОДУ
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
.code
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
; Головна Процедура
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
main PROC C
LOCAL hStdout :DWORD ;(1)
;-----compute------
push dword ptr vF
push dword ptr vF
push vE
push vC
push dword ptr vB
push dword ptr vB
push dword ptr vA + 4
push dword ptr vA
call calcLab3
;------------------
;назва консолі
push offset sConsoleTitle ;(2)
call SetConsoleTitleA
;отримуємо хендл виводу ;(3)
push -11
call GetStdHandle
mov hStdout,EAX
push offset sWriteText
call strlen; eax = strlen(sWriteText)
add esp, 4
;виводимо HELLO, WORLD! ;(4)
push 0
push 0
push eax; 16d ;
push offset sWriteText
push hStdout
call WriteConsoleA
;затримка щоб побачити результат;(5)
push 2000d
call Sleep
;выход ;(6)
push 0
call ExitProcess
main ENDP
calcLab3 PROC
finit
push ebp
mov ebp, esp
fld dword ptr [ebp + 20] ;C
fld dword ptr [ebp + 24] ;E
fld dword ptr [ebp + 28] ;F
fmul ;E*F
mov dword ptr temp, K
fild temp
fsubr ;K-E*F
fdiv ;C/(K-E*F)
fld qword ptr [ebp + 8] ;A
fld dword ptr [ebp + 16] ;B
fmul ;A*B
fadd ;A*B+C/(K-E*F)
fst temp
push dword ptr temp[4]
push dword ptr temp[0]
push OFFSET fmt
push OFFSET sWriteText
call sprintf
add esp, 16
pop ebp
ret 32
calcLab3 ENDP
end main
/
4.2.2
#define _CRT_SECURE_NO_WARNINGS
#define WIN32_LEAN_AND_MEAN // компоненти з заголовків Windows, що рідко застосовуються
#define MAX_SIZE_WRITE_TEXT 1024
#include <windows.h>
#include "stdio.h"
#include <math.h>
TCHAR sConsoleTitle[] = L"My First Console Application";
char sWriteText[MAX_SIZE_WRITE_TEXT] = { 0 }; // "HELLO, WORLD!!!!"
char fmt[] = "result = %.3lf\r\n";
//X= A2*B1+C1/ (K-E1*F1)
#define K 1 //(153136)
extern "C" void calcLab3(double a2, float b1, float c1, float e1, float f1){
sprintf(sWriteText, fmt, a2*(double)b1+((double)c1/((double)K - ((double)e1*(double)f1))));
}
int main(){
HANDLE std_out; // (1)
// -----compute------
double a2 = 10.;
float b1 = 20.;
float c1 = 30.;
float e1 = 40.;
float f1 = 50.;
calcLab3(a2, b1, c1, e1, f1);
// ------------------
SetConsoleTitle(sConsoleTitle); // (2)
std_out = GetStdHandle(STD_OUTPUT_HANDLE); // (3)
WriteConsoleA(std_out, sWriteText, strlen(sWriteText), NULL, NULL);// (4)
Sleep(2000);// (5)
ExitProcess(0);// (6)
return 0;
}
/
4.3.1
; window.asm
; Графічна win32-програма, виводить вікно і міняє заголовок при натисканні лівої клавіші
; мишки.
.386
.model flat
EXTRN _sprintf:near
include def32.inc
include kernel32.inc
include user32.inc
;includelib libcmt.lib; for new vs(from vs2015)
;includelib libvcruntime.lib; for new vs(from vs2015)
;includelib libucrt.lib; for new vs(from vs2015)
;includelib legacy_stdio_definitions.lib; for new vs(from vs2015)
includelib msvcrt.lib; for old vs(to vs2013)
;includelib masm32\lib\msvcrt.lib; for masm32p
;includelib \masm32\lib\msvcrt.lib; for masm32
;includelib masm32\lib\user32.lib; for masm32p
;includelib masm32\lib\kernel32.lib; for masm32p
;includelib masm32\lib\shell32.lib; for masm32p
;includelib \masm32\lib\user32.lib; for masm32
;includelib \masm32\lib\kernel32.lib; for masm32
;includelib \masm32\lib\shell32.lib; for masm32
.data
class_name db "Window class 1",0
window_name db "Win32 assembly example",0
wnd_text db "Hello ",0
fmt db "result: x[%d] = %lf, x[%d] = %lf, x[%d] = %lf", 13, 10, 0;
temp1 dd 0
temp2 dd 0
oper dd 0
temp3 qword ?
CONST_41 dd 41.0;
CONST_28 dd 28.0;
CONST_4 dd 4.0;
CONST_2 dd 2.0;
CONST_1 dd 1.0;
CONST_53 equ 53d;
;CONST_28 equ 28d;
CONST_5 equ 5d;
temp qword ?
CONST_53 equ 53d;
CONST_5 equ 5d;
cV dd 1.; c
dV dd 1.;
a dq 10., 20., 30.;
x dq ?, ?, ?;
; Структура, що описує клас вікна.
wc WNDCLASSEX <4*12,CS_HREDRAW or CS_VREDRAW,Offset win_proc,0,0,?,?,?,\
COLOR_WINDOW+1,0,offset class_name,0>
; Тут знаходяться наступні поля:
; wc.cbSize = 4*12 - розмір цієї структури
; wc.style - стиль вікна (як перемальовувати його то)
; wc.lpfnWndProc – обробник подій вікна (віконна процедура win_proc)
; wc.cbClsExtra - число додаткових байт після структури (0)
; wc.cbWndExtra - число додаткових байт після вікна (0)
; we.hInstance - ідентифікатор нашого процеса (?)
; wc.hIcon - ідентифікатор іконки (?)
; wc.hCursor - ідентифікатор курсора (?)
; wc.hbrBackground - ідентифікатор пензлика або колір фона + 1(COLOR_WINDOW+1)
; wc.lpszMenuName - ресурс з основним меню (в цьому прикладі - 0)
; wc.lpszClassName - імя класса (рядок class.name)
; wc.hIconSm - ідентифікатор маленької іконки (тільки в Windows 95,
; для NT має бути 0).
.data?
msg_ MSG <?,?,?,?,?,?> ; А це - структура, в яку повертається
; повідомлення після GetMessage
.code
WinMain@16 proc c
;-----compute------
push 3
push dV
push cV
push OFFSET a
push OFFSET x
call calcLab4 ;
push 3
push OFFSET x
call printResult
;------------------
xor ebx,ebx ; В ЕВХ буде 0 для команд push 0.
; Визначити ідентифікатор нашої програми
push ebx
call GetModuleHandle
mov esi,eax ; і зберегти його в ESI.
; Заповнити й зареєструвати клас.
mov dword ptr wc.hInstance,eax ; Ідентифікатор предка. ; Вибрати іконку.
push IDI_APPLICATION ; Стандартна іконка додатка.
push ebx ; Ідентифікатор модуля з іконкою,
call LoadIcon
mov wc.hIcon,eax ; Ідентифікатор іконки для нашого класу.
; Вибрати форму курсора
push IDC_ARROW ; Стандартна стрілка.
push ebx ; Ідентифікатор модуля з курсором
call LoadCursor
mov wc.hCursor,eax ; Ідентифікатор курсору для нашого класу
push offset wc
call RegisterClassEx ; Зареєструвати клас.
; Створити вікно
mov ecx,CW_USEDEFAULT ; push ecx коротше push N у п'ять разів.
push ebx ; Адреса структури CREATESTRUCT (тут NULL)
push esi ; Ідентифікатор процесу, що буде одержувати
; повідомлення від вікна (тобто наш).
push ebx ; Ідентифікатор меню або вікна-нащадка.
push ebx ; Ідентифікатор вікна-предка,
push ecx ; Висота (CW_USEOEFAULT - за замовчуванням)
push ecx ; Ширина (за замовчуванням),
push ecx ; Y-координата (за замовчуванням)
push ecx ; Х-координата (за замовчуванням),
push WS_OVERLAPPEDWINDOW ; Стиль вікна,
push offset window_name ; Заголовок вікна,
push offset class_name ; Любою зареєстрований клас,
push ebx ; Додатковий стиль
call CreateWindowEx ; Створити вікно (еах - ідентифікатор вікна)
push eax ; Ідентифікатор для UpdateWіndow.
push SW_SHOWNORMAL ; Тип показу для для ShowWіndow
push eax ; Ідентифікатор для ShowWіndow.
; Більше ідентифікатор вікна нам не буде потрібний
call ShowWindow ; Показати вікно
call UpdateWindow ; і послати йому повідомлення WM_PAІNT.
; Основний цикл - перевірка повідомлень від вікна й вихід no WM_QUІT.
mov edi, offset msg_ ; push edі коротше push N в 5 разів.
message_loop:
push ebx ; Останнє повідомлення.
push ebx ; Перше повідомлення
push ebx ; Ідентифікатор вікна (0 - будь-яке наше вікно)
push edi ; Адреса структури MSG
call GetMessage ; Одержати повідомлення від вікна з очікуванням -
; не забувайте використати PeekMessage.
; якщо потрібно в цьому циклі щось виконувати.
test eax,eax ; Якщо отримано WM_QUІT.
jz exit_msg_loop ; вийти.
push edi ; Інакше - перетворити повідомлення типу
call TranslateMessage ; WM_KEYUP у повідомлення типу WM_CHAR
push edi
call DispatchMessage ; і послати їх процедурі вікна (інакше його просто
; не можна буде закрити)
jmp short message_loop ; Продовжити цикл
exit_msg_loop:
;Вихід із програми.
push ebx
call ExitProcess
WinMain@16 endp
; Процедура wіn_proc
; Викликається вікном щораз, коли воно одержує яке-небудь повідомлення.
; Саме тут буде відбуватися вся робота програми.
; Процедура не повинна змінювати регістри EBP, EDІ, ESІ й ЕВХ!
win_proc proc
; Тому що ми одержуємо параметри в стеці, побудувати стековый кадр.
push ebp
mov ebp,esp
; Процедура типу WіndowProc викликається з наступними параметрами:
wp_hWnd equ dword ptr [ebp+08h] ; ідентифікатор вікна,
wp_uMsg equ dword ptr [ebp+0Ch] ; номер повідомлення,
wp_wParam equ dword ptr [ebp+10h] ; перший параметр,
wp_lParam equ dword ptr [ebp+l4h] ; другий параметр.
; Якщо ми одержали повідомлення WM_DESTROY (воно означає, що вікно вже видалили
; з екрана, нажавши ALT+F4 або кнопку у верхньому правому куті),
; то відправимо основній програмі повідомлення WM_QUІT.
cmp wp_uMsg,WM_DESTROY
jne not_wm_destroy
push 0 ; Код виходу.
call PostQuitMessage ; Послати WM_QUІT
jmp short end_wm_check ; і вийти із процедури.
not_wm_destroy:
cmp wp_uMsg,WM_LBUTTONDOWN
je wm_lbutdwn
; Якщо ми одержали інше повідомлення - викликати його оброблювач за замовчуванням.
leave ; Відновити ebp
jmp DefWindowProc ; і викликати DefWіndowProc з нашими параметрами
; і адресою повернення в стеці.
wm_lbutdwn:
; Вивести текст у заголовку вікна
push offset wnd_text
push wp_hWnd
call SetWindowText
leave
jmp DefWindowProc ; Після внесення своїх зміни в стандартний хід опрацювання
; повідомлення треба дати програмі завершити опрацювання
; стандартним чином
end_wm_check:
leave ; Відновити ebp
ret 16 ; і повернутися самим, очистивши стек від параметрів.
win_proc endp
calcLab4 PROC
finit
push ebp
mov ebp, esp
mov ecx, dword ptr [ebp + 24]
xor esi, esi; (mov esi, 0)
fld dword ptr [ebp + 16] ; c
fld dword ptr [ebp + 20] ; d
fcompp
;xor eax, eax
fstsw ax
sahf
jnb compute_loop_2; // if (c <= d) goto compute_loop_2;
mov ebx, dword ptr [ebp + 12] ; a
fld qword ptr [ebx + 8 * esi]; a[esi]
fld dword ptr [ebp + 20] ; d
fdiv dword ptr [ebp + 16]
fadd
fst temp
compute_loop_1: ; // if (c > d);
mov ebx, dword ptr [ebp + 12] ; a
fld qword ptr [ebx + 8 * esi]; a[esi]
fld dword ptr [ebp + 16] ; c
fdiv CONST_4
fsub
fld CONST_1
fadd
fst temp2
finit
fld temp
fld temp2
fdiv;
mov ebx, dword ptr [ebp + 8] ; x
fst qword ptr [ebx + 8 * esi] ; x[esi]
inc esi
loop compute_loop_1
jmp output
;_____________________________________________________________
compute_loop_2: ; // if (c <= d);
fld CONST_41
fmul dword ptr [ebp + 20]; d
mov ebx, dword ptr [ebp + 12] ; a
fld qword ptr [ebx + 8 * esi]; a[esi]
fdiv
fsqrt
fld CONST_1
fadd
fst temp
mov ebx, dword ptr [ebp + 12] ; a
fld qword ptr [ebx + 8 * esi]; a[esi]
fld dword ptr [ebp + 16] ; c
fdiv dword ptr [ebp + 20]
fsub
fst temp3
finit
fld temp
fld temp3
fdiv;
mov ebx, dword ptr [ebp + 8] ; x
fst qword ptr [ebx + 8 * esi] ; x[esi]
inc esi
loop compute_loop_2
jmp output
output:
pop ebp
ret 20
;_____________________________________________________________
calcLab4 ENDP
mov ebx, dword ptr [ebp + 12] ; a
fld qword ptr [ebx + 8 * esi]; a[esi]
printResult PROC
push ebp
mov ebp, esp
mov ecx, dword ptr [ebp + 12] ; mov ecx, dword ptr [ebp + 24]; (for motod 2)
mov esi, ecx
dec esi
mov ebx, dword ptr [ebp + 8] ; x
output_loop:
;mov edx, dword ptr [ebx + 8 * esi + 4];
;mov eax, dword ptr [ebx + 8 * esi];
;push edx;
;push eax;
push dword ptr [ebx + 8 * esi + 4];
push dword ptr [ebx + 8 * esi];
push esi
dec esi
loop output_loop
push OFFSET fmt
push OFFSET wnd_text
call _sprintf
add esp, 8
mov eax, dword ptr [ebp + 12] ; mov ecx, dword ptr [ebp + 24]; (for motod 2)
mov ecx, 12
mul ecx
add esp, eax ; 8(4+4) + n*8(4+4)
pop ebp;
ret 8 ; ret 20; (for motod 2)
printResult ENDP
;end; for new vs(from vs2015)
end WinMain@16; for old vs(to vs2013) and masm32/masm32p
/
4.3.2
#define _CRT_SECURE_NO_WARNINGS
#define _CRT_NON_CONFORMING_SWPRINTFS
#define WIN32_LEAN_AND_MEAN // компоненти з заголовків Windows, що рідко застосовуються
#define MAX_SIZE_WND_TEXT 1024
#include <windows.h>
#include "stdio.h"
#include <math.h>
#include <cmath>
wchar_t class_name[] = L"Window class 1";
wchar_t window_name[] = L"Win32 assembly example";
wchar_t wnd_text[MAX_SIZE_WND_TEXT] = { 0 }; // L"Hello";
#define MAX_ARRAY_SIZE 256
#define ARRAY_SIZE = 3
#define ARRAY_VALUES = {10., 20., 30.}
#define C_VALUE = 1.
#define D_VALUE = 1.
LRESULT CALLBACK win_proc(HWND wp_hWnd, UINT wp_uMsg, WPARAM wp_wParam, LPARAM wp_lParam);
void calcPract4ByLab4(double * x, double * a, float c, float d, int n){
for (int index = 0; index < n; ++index){
if (c > d) {
x[index] =(a[index]+(d/c))/(a[index]-(c/4)+1) ; // (c > d)
}
else{
x[index] = (sqrt((41*d)/a[index])+1)/(a[index] - (c/d)) ;// (c <= d)
}
}
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR lpCmdLine, int nCmdShow)
{
int n ARRAY_SIZE;
double a[MAX_ARRAY_SIZE] ARRAY_VALUES, x[MAX_ARRAY_SIZE];// ARRAY_VALUES;
float c C_VALUE;
float d D_VALUE;
calcPract4ByLab4(x, a, c, d, n);
swprintf(wnd_text, L"Result = [%lf][%lf][%lf]", x[0], x[1], x[2]);
MSG msg_;
HWND hWnd;
WNDCLASSEX wc;
wc.cbSize = sizeof(wc);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = win_proc;
wc.cbClsExtra = NULL;
wc.cbWndExtra = NULL;
wc.hbrBackground = HBRUSH(COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = class_name;
wc.hIconSm = NULL;
wc.hInstance = GetModuleHandle(NULL); /*handle to the file used to create the calling process */
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
RegisterClassEx(&wc);
hWnd = CreateWindowEx(
NULL,
class_name,
window_name,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
(HMENU)NULL,
wc.hInstance,
NULL);
ShowWindow(hWnd, SW_SHOWNORMAL);
UpdateWindow(hWnd);
while (GetMessage(&msg_, NULL, NULL, NULL)) {
TranslateMessage(&msg_);
DispatchMessage(&msg_);
}
return msg_.wParam;
}
//Віконна процедура
LRESULT CALLBACK win_proc(HWND wp_hWnd, UINT wp_uMsg, WPARAM wp_wParam, LPARAM wp_lParam)
{
switch (wp_uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_LBUTTONDOWN:
SetWindowText(wp_hWnd, wnd_text);
break;
default:
return DefWindowProc(wp_hWnd, wp_uMsg, wp_wParam, wp_lParam);
}
return 0;
}