Міністерство освіти і науки України
Національний університет “Львівська політехніка”
Кафедра АСУ
Звіт до
лабораторної роботи №3
з курсу « Системного програмування»
на тему «Робота з пам’яттю»
Тема – робота з пам’яттю.
Мета – навчитися використовувати системну пам’ять та розміщати в ній дані з файлу.
ТЕОРЕТИЧНІ ПОЛОЖЕННЯ
Пам’ять є основним ресурсом при програмуванні в багатозадачному середовищі. Множина вільних фрагментів пам’яті називається хіп (від англійського слова HEAP). Програміст може виділити для своєї програми блок пам’яті будь-якої довжини, що не перевищує загальний об’єм вільної пам’яті. В Windows пам’ять виділяється в 2 етапи:
спочатку система виділяє фрагмент віртуальної пам’яті, який отримує свій хендл, але не отримує реальної адреси;
потім система розміщує (блокує) цей фрагмент у реальній пам’яті і фрагмент отримує початкову адресу.
Після того, як програміст отримує адресу початку виділеного блоку, він може її використовувати. Комірки з адресами до початку та після кінця блоку використовувати не можна, тому що вони належать іншим програмам або системі.
Після того, як програма використала блок пам’яті, його необхідно розблокувати. Таким чином, він знову стає віртуальним, і при необхідності може бути переміщений системою в інше місце або на диск. Якщо програма довго не розблоковує блок пам’яті, то це негативно відображається на продуктивності операційної системи в цілому. Отже, якщо після розблокування пам’яті її знову заблокувати, адреса початку блоку може бути іншою. Якщо програміст взагалі відмовляється від використання виділеного блоку пам’яті, він повинен звільнити блок, що веде до знищення його хендла. Очевидно, що перед звільненням блоку пам’яті його необхідно розблокувати.
В лабораторній роботі запропонована програма, яка виділяє блок пам’яті зчитує у виділений фрагмент файл виводить його на екран та звільняє виділений блок.
Для відкриття, читання та запису файлів використовуються відповідні функції API, опис яких ви знайдете після тексту програми.
Завдання:
Вивести інформацію о пам’яті
Код: (inc файл)
include kernel32.inc
include user32.inc
includelib IMPORT32.LIB
GMEM_MOVEABLE equ 2h
GMEM_ZEROINIT equ 40h
MEMSIZE equ 1000000h ; 16 Mb
.data
pMem dd 0
MEMORYSTATUS :
dwLength DWORD 0 ; Размер структуры
dwMemoryLoad DWORD 0 ; Процент использования памяти
dwTotalPhys DWORD 0 ; Физическая память, байт
dwAvailPhys DWORD 0 ; Свободная физическая память, байт
dwTotalPageFile DWORD 0 ; Размер файла подкачки, байт
dwAvailPageFile DWORD 0 ; Свободных байт в файле подкачки
dwTotalVirtual DWORD 0 ; Виртуальная память, используемая процессом
dwAvailVirtual DWORD 0 ; Свободная виртуальная память
hFile dd 0
read_byte dd 0
FORMAT2 db "Вiдсоток зайнятостi = %ld %%",0dh
db "Загальна оперативна пам'ять: %ld Kb",0dh
db "З неї доступно: %ld Kb",0dh
db "Розмiр файлу свопiнга: %ld",0dh
db "Вiльного мiсця в ньому: %ld",0dh
db "Квота вiртуальної пам'ятi: %ld Kb",0dh
db "З неї вiльно: %ld Kb",0
buf1 db 260 dup(0)
save_esp dd 0
szTitle_lab db 'Лабораторна робота №3',0
Код: (asm файл)
.386
.model flat,stdcall
include l3.inc
.code
Mem_Alloc PROC Buf_Size:DWORD
add Buf_Size,4 ; виділяємо буфер на 4 бати більший
call GlobalAlloc,GMEM_MOVEABLE or GMEM_ZEROINIT,Buf_Size
push eax
call GlobalLock,eax
pop [eax] ;запишемо у перші 4 байти хенд області виділеного буфера
;наступні Buf_Size байт використовуємо як масив
add eax,4 ;зсуваємо вказівних початку масиву на 4 байти, оскільки перші 4 байти
;заняті значенням хендлу буфера
ret
Mem_Alloc endp
Mem_Free PROC DATA:DWORD
mov eax,DATA ;копіюємо значення параметра процедури у регістр eax, параметром є
;початкова (робоча) адреса буфера, тобто початок + 4 байти
sub eax,4 ;пам'ятаємо, що перших 4 байти масиву - це хендл буфера
push [eax] ;беремо чотирьох байтне значення по адресі, що лежить у регістрі
;eax, заносимо його у стек
call GlobalUnlock,eax ;розблоковуємо пам'ять (всю розміром Buf_Size+4)
call GlobalFree ;оскільки параметр вже у стеці, викликаємо процедуру без
;параметрів, за дапомогою інструкції call (знищуємо хендел буфера)
ret
Mem_Free endp
begin:
;видыляємо память
call Mem_Alloc,MEMSIZE
mov pMem,eax
; визначаємо властивості пам"яті
mov dwLength,8*4 ; розмір структури
call GlobalMemoryStatus,pmem
;зберіг вказівник верхівки стеку
mov save_esp,esp
mov edi,pmem
call GlobalMemoryStatus,pmem
call MulDiv,[edi+8],1,1024
mov dwTotalPhys,eax
call MulDiv,[edi+12],1,1024
mov dwAvailPhys,eax
call MulDiv,[edi+24],1,1024
mov dwTotalVirtual,eax
call MulDiv,[edi+28],1,1024
mov dwAvailVirtual,eax
call wsprintf,offset BUF1,offset FORMAT2,[edi+4],dwTotalPhys,\
dwAvailPhys,[edi+16],[edi+20],dwTotalVirtual,dwAvailVirtual
; відновлюємо значення вказівника стеку
mov esp,save_esp
;віводимо повідомлення (результат)
call MessageBox,0,offset buf1,offset szTitle_lab,0
Exit:
;звільняємо пам"ять
call Mem_Free,pMem
;віхід
call ExitProcess,0
end begin
/
Висновок:
виконавши лабораторну роботу я навчився працювати з пам'яттю.