Функция VirtualAlloc – резервирование региона в адресном пространстве.
Создание приложения для работы с виртуальной памятью.
2. Выведите на экран изображения символов второй половины ASCII таблицы символов (коды от 128 до 255).
3. Напишите программу, которая 10 раз выводит на экран какой-либо сообщение.
Анализ технического задания
1. Написать программу в Delphi7 для получения информации о состоянии системной памяти и виртуальной памяти.
Открываем Delphi7 и в форму добавляем компоненты:
Form1 - Virtual Memory;
Button1 - кнопка «SysInfo»;
Button2 - кнопка «GlobalMemorySatus»;
Button3 - кнопка «VirtualQuery»;
Button4 - кнопка «VirtualAlloc»;
Button5 - кнопка «VirtualFree»;
Button6 - кнопка «Выход»;
Button7 - кнопка «VirtualProtect»;
Button8 - кнопка «Свободные регионы»;
ComboBox1 - Элемент защиты;
Edit1 - Окно ввода виртуальной памяти;
Edit2 - Окно ввода количество выделяемых при резервировании региона в адресном пространстве байт;
Label1 - Введите адрес виртуальной памяти;
Label2 - Выберите элемент защиты;
Label3 - Введите количество выделяемых при резервировании;
Label4 - региона в адресном пространстве байт;
Memo1 - Окно для вывода информации;
Memo2 - Окно для вывода свободных регионов;
2. Вывод изображения символов второй половины ASCII (от 128 до 255).
Создаём блокнот и вставляем текст программы. После файл сохранили на диск С с расширением asm. (AS.asm). При использовании пакета TASM получение объектного модуля исходного файла производится программой (ассемблером) tasm.exe. Пакет так же сохранили на диск.
Трансляция программыAS.asm выполняется командной строкой вида:TASM.EXE /zi AS, , , .В результате на диске созданы файлы AS.obj, AS.lstlist, AS.crf. Далее - компоновка. Результатом работы компоновщика является создание загрузочного файла с расширением .ехе.
Для выполнения примера следует запустить программу tlink.exe командной строкой вида tlink.exe /v AS.obj. В результате получится исполняемый модуль с расширением .ехе — AS.exe. Вызываем его с помощью командной строки, набирая команду: Пуск/Выполнитm/cmd.exe, далее C:\Document and Settings\User>chdir C:\tasm\bin, далее набираем C:\tasm\biт>AS.exe, и получаем сообщение со всеми символами.
3. Вывод 10 сообщения “hello,world!”
Создаём блокнот и вставляем текст программы. После файл сохранили на диск С с расширением asm. (hw10.asm). При использовании пакета TASM получение объектного модуля исходного файла производится программой (ассемблером) tasm.exe. Пакет так же сохранили на диск.
Трансляция программыhw10.asm выполняется командной строкой вида:TASM.EXE /zi hw10, , , .В результате на диске созданы файлы HW10.obj, HW10.lstlist, HW10.crf. Далее - компоновка. Результатом работы компоновщика является создание загрузочного файла с расширением .ехе.
Для выполнения примера следует запустить программу tlink.exe командной строкой вида tlink.exe /v HW10.obj. В результате получится исполняемый модуль с расширением .ехе — HW10.exe. Вызываем его с помощью командной строки, набирая команду: Пуск/Выполнитm/cmd.exe, далее C:\Document and Settings\User>chdir C:\tasm\bin, далее набираем C:\tasm\biт>HW10.exe, и получаем 10 раз сообщение «hello,World!».
Текст программы
Задание 1 (Программа 1)
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
Button4: TButton;
Button5: TButton;
Button6: TButton;
Label1: TLabel;
Edit1: TEdit;
Memo1: TMemo;
ComboBox1: TComboBox;
Label2: TLabel;
Button7: TButton;
Label3: TLabel;
Label4: TLabel;
Edit2: TEdit;
Button8: TButton;
Memo2: TMemo;
procedure FormActivate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure Button5Click(Sender: TObject);
procedure Button6Click(Sender: TObject);
procedure Button7Click(Sender: TObject);
procedure Button8Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
p: pointer;
implementation
{$R *.dfm}
procedure TForm1.FormActivate(Sender: TObject);
begin
Memo1.Clear;
Memo2.Clear;
end;
procedure TForm1.Button1Click(Sender: TObject);
var // SysInf: TSystemInfo;
SysInf: SYSTEM_INFO;
begin
GetSystemInfo(SysInf);
Memo1.Clear;
Memo1.Lines.Add('Размер страницы: '+IntToStr(SysInf.dwPageSize)+' байт');
Memo1.Lines.Add('Процессор: '+IntToStr(SysInf.wProcessorArchitecture));
Memo1.Lines.Add('Зарезервировано: '+IntToStr(SysInf.wReserved));
Memo1.Lines.Add('Количество процессоров: '+IntToStr(SysInf.dwNumberOfProcessors));
Memo1.Lines.Add('Маска активного процессора: '+IntToStr(SysInf.dwActiveProcessorMask));
Memo1.Lines.Add('Тип процессора: '+IntToStr(SysInf.dwProcessorType));
Memo1.Lines.Add('Гранулярность выделения ресурсов: '+IntToStr(SysInf.dwAllocationGranularity));
Memo1.Lines.Add('Архитектура процессора: '+IntToStr(SysInf.wProcessorLevel));
Memo1.Lines.Add('Уровень архитектуры процессора: '+IntToStr(SysInf.wProcessorRevision));
end;
procedure TForm1.Button2Click(Sender: TObject);
var // ms: MEMORYSTATUS;
ms: TMEMORYSTATUS;
begin
ms.dwLength:=SizeOf(MEMORYSTATUS);
GlobalMemoryStatus(ms);
Memo1.Clear;
Memo1.Lines.Add('Загружено памяти: '+IntToStr(ms.dwMemoryLoad));
Memo1.Lines.Add('Всего физическая память: '+IntToStr(ms.dwTotalPhys)+' байт');
Memo1.Lines.Add('Доступная физическая память: '+IntToStr(ms.dwAvailPhys)+' байт');
Memo1.Lines.Add('Общий размер страничного файла: '+IntToStr(ms.dwTotalPageFile)+' байт');
Memo1.Lines.Add('Доступный размер страничного файла: '+IntToStr(ms.dwAvailPageFile)+' байт');
Memo1.Lines.Add('Общий размер виртуальной памяти: '+IntToStr(ms.dwTotalVirtual)+' байт');
Memo1.Lines.Add('Доступный размер виртуальной памяти: '+IntToStr(ms.dwAvailVirtual)+' байт');
end;
procedure TForm1.Button3Click(Sender: TObject);
var // mbi: MEMORY_BASIC_INFORMATION;
mbi: TMemoryBasicInformation;
dwRez: DWORD;
begin
If Edit1.GetTextLen<=0 then
ShowMessage('Введите виртуальный адрес')
else
begin
dwRez:=VirtualQuery(pointer(StrToInt(Edit1.Text)),mbi,sizeof(MEMORY_BASIC_INFORMATION));
Memo1.Clear;
Memo1.Lines.Add('Базовый адрес: '+IntToStr(integer(mbi.BaseAddress)));
Memo1.Lines.Add('Адрес размещения: '+IntToStr(integer(mbi.BaseAddress)));
case mbi.AllocationProtect of
0: Memo1.Lines.Add('ВАП зарезервировано');
PAGE_NOACCESS: Memo1.Lines.Add('Атрибут защиты ВАП: PAGE_NOACCESS');
PAGE_READONLY: Memo1.Lines.Add('Атрибут защиты ВАП: PAGE_READONLY');
PAGE_READWRITE: Memo1.Lines.Add('Атрибут защиты ВАП: PAGE_READWRITE');
PAGE_EXECUTE: Memo1.Lines.Add('Атрибут защиты ВАП: PAGE_EXECUTE');
PAGE_EXECUTE_READ: Memo1.Lines.Add('Атрибут защиты ВАП: PAGE_EXECUTE_READ');
PAGE_EXECUTE_READWRITE: Memo1.Lines.Add('Атрибут защиты ВАП: PAGE_EXECUTE_READWRITE');
PAGE_WRITECOPY: Memo1.Lines.Add('Атрибут защиты ВАП: PAGE_WRITECOPY');
PAGE_EXECUTE_WRITECOPY: Memo1.Lines.Add('Атрибут защиты ВАП: PAGE_EXECUTE_WRITECOPY');
end;
Memo1.Lines.Add('Размер региона: '+IntToStr(mbi.RegionSize)+' байт');
case mbi.State of
MEM_COMMIT: Memo1.Lines.Add('Состояние ВАП: MEM_COMMIT');
MEM_RESERVE: Memo1.Lines.Add('Состояние ВАП: MEM_RESERVE');
MEM_FREE: Memo1.Lines.Add('Состояние ВАП: MEM_FREE');
end;
case mbi.Protect of
0: Memo1.Lines.Add('Зарезервировано');
PAGE_NOACCESS: Memo1.Lines.Add('Атрибут защиты физ.памяти: PAGE_NOACCESS');
PAGE_READONLY: Memo1.Lines.Add('Атрибут защиты ВАП: PAGE_READONLY');
PAGE_READWRITE: Memo1.Lines.Add('Атрибут защиты ВАП: PAGE_READWRITE');
PAGE_EXECUTE: Memo1.Lines.Add('Атрибут защиты ВАП: PAGE_EXECUTE');
PAGE_EXECUTE_READ: Memo1.Lines.Add('Атрибут защиты ВАП: PAGE_EXECUTE_READ');
PAGE_EXECUTE_READWRITE: Memo1.Lines.Add('Атрибут защиты ВАП: PAGE_EXECUTE_READWRITE');
PAGE_WRITECOPY: Memo1.Lines.Add('Атрибут защиты ВАП: PAGE_WRITECOPY');
PAGE_EXECUTE_WRITECOPY: Memo1.Lines.Add('Атрибут защиты ВАП: PAGE_EXECUTE_WRITECOPY');
end;
end;
end;
procedure TForm1.Button4Click(Sender: TObject);
var ms: MEMORYSTATUS;
Size: integer;
begin
If Edit2.GetTextLen=0 then
Size:=4096
else
Size:=StrToInt(Edit2.Text);
If Edit1.GetTextLen=0 then
p:=VirtualAlloc(nil,Size,MEM_COMMIT,PAGE_READWRITE)
else
p:=VirtualAlloc(pointer(StrToInt64(Edit1.Text)),Size,MEM_COMMIT,PAGE_READWRITE);
ms.dwLength:=sizeof(MEMORYSTATUS);
GlobalMemoryStatus(ms);
Memo1.Clear;
Memo1.Lines.Add('Загружено памяти: '+IntToStr(ms.dwMemoryLoad)+' байт');
Memo1.Lines.Add('Всего физическая память: '+IntToStr(ms.dwTotalPhys)+' байт');
Memo1.Lines.Add('Доступная физическая память: '+IntToStr(ms.dwAvailPhys)+' байт');
Memo1.Lines.Add('Общий размер страничного файла: '+IntToStr(ms.dwTotalPageFile)+' байт');
Memo1.Lines.Add('Доступный размер страничного файла: '+IntToStr(ms.dwAvailPageFile)+' байт');
Memo1.Lines.Add('Общий размер виртуальной памяти: '+IntToStr(ms.dwTotalVirtual)+' байт');
Memo1.Lines.Add('Доступный размер виртуальной памяти: '+IntToStr(ms.dwAvailVirtual)+' байт');
end;
procedure TForm1.Button5Click(Sender: TObject);
var ms: MEMORYSTATUS;
begin
VirtualFree(p,4096,MEM_DECOMMIT);
VirtualFree(p,4096,MEM_RELEASE);
ms.dwLength:=SizeOf(MEMORYSTATUS);
GlobalMemoryStatus(ms);
Memo1.Clear;
Memo1.Lines.Add('Загружено памяти: '+IntToStr(ms.dwMemoryLoad)+' байт');
Memo1.Lines.Add('Всего физической памяти: '+IntToStr(ms.dwTotalPhys)+' байт');
Memo1.Lines.Add('Доступная физическая память: '+IntToStr(ms.dwAvailPhys)+' байт');
Memo1.Lines.Add('Общий размер страничного файла: '+IntToStr(ms.dwTotalPageFile)+' байт');
Memo1.Lines.Add('Доступный размер страничного файла: '+IntToStr(ms.dwAvailPageFile)+' байт');
Memo1.Lines.Add('Общий размер виртуальной памяти: '+IntToStr(ms.dwTotalVirtual)+' байт');
Memo1.Lines.Add('Доступный размер виртуальной памяти: '+IntToStr(ms.dwAvailVirtual)+' байт');
end;
procedure TForm1.Button6Click(Sender: TObject);
begin
Form1.Close;
end;
procedure TForm1.Button7Click(Sender: TObject);
var ms: MEMORYSTATUS;
OldProtect: pointer;
begin
If ComboBox1.Text='' then
ShowMessage('Выберите элемент защиты')
else
begin
If ComboBox1.Text='PAGE_NOACCESS' then
VirtualProtect(p,4096,PAGE_NOACCESS,OldProtect);
If ComboBox1.Text='PAGE_READONLY' then
VirtualProtect(p,4096,PAGE_READONLY,OldProtect);
If ComboBox1.Text='PAGE_EXECUTE' then
VirtualProtect(p,4096,PAGE_EXECUTE,OldProtect);
If ComboBox1.Text='PAGE_EXECUTE_READ' then
VirtualProtect(p,4096,PAGE_EXECUTE_READ,OldProtect);
If ComboBox1.Text='PAGE_EXECUTE_READWRITE' then
VirtualProtect(p,4096,PAGE_EXECUTE_READWRITE,OldProtect);
If ComboBox1.Text='PAGE_WRITECOPY' then
VirtualProtect(p,4096,PAGE_WRITECOPY,OldProtect);
If ComboBox1.Text='PAGE_EXECUTE_WRITECOPY' then
VirtualProtect(p,4096,PAGE_EXECUTE_WRITECOPY,OldProtect);
end;
ms.dwLength:=SizeOf(MEMORYSTATUS);
GlobalMemoryStatus(ms);
Memo1.Clear;
Memo1.Lines.Add('Загружено памяти: '+IntToStr(ms.dwMemoryLoad)+' байт');
Memo1.Lines.Add('Всего физической памяти: '+IntToStr(ms.dwTotalPhys)+' байт');
Memo1.Lines.Add('Доступная физическая память: '+IntToStr(ms.dwAvailPhys)+' байт');
Memo1.Lines.Add('Общий размер страничного файла: '+IntToStr(ms.dwTotalPageFile)+' байт');
Memo1.Lines.Add('Доступный размер страничного файла: '+IntToStr(ms.dwAvailPageFile)+' байт');
Memo1.Lines.Add('Общий размер виртуальной памяти: '+IntToStr(ms.dwTotalVirtual)+' байт');
Memo1.Lines.Add('Доступный размер виртуальной памяти: '+IntToStr(ms.dwAvailVirtual)+' байт');
end;
procedure TForm1.Button8Click(Sender: TObject);
var mbi: TMemoryBasicInformation;
n, k: DWORD;
begin
Memo2.Clear;
n:=00000000;
k:=11111111;
While n<k do
begin
VirtualQuery(pointer(n),mbi,SizeOf(MEMORY_BASIC_INFORMATION));
If mbi.State=MEM_FREE then
Memo2.Lines.Add(IntToStr(n));
Inc(n,mbi.RegionSize);
end;
end;
end.
Задание 2 (Программа 2)
; кодовый сегмент
cseg segment 'code'
assume cs:cseg, ds:dseg, ss:sseg
mypr proc
mov ax,sseg ;в регистр ax записывается указатель
;на начало cтекового сегмента
mov ss,ax ; в сегмент стека записывается адрес
;начала стека
mov sp, offset TOS ; в указатель стека
;записывается адрес стека
mov ax,dseg ; в регистр ах записывается
;адрес сегмента данных
mov ds,ax ; адрес сегмента данных
;записывается в регистр ds
mov cx,128 ; в регистр сх записывается
;счетчик цикла - 128
mov al,'Ђ' ; в регистр al записывается код
;первого символа
mov si,0 ; в регистр si записывается 0
;(смещение в строке mes)
f1: mov mes[si],al ; содержимое регистра al
; записывается в строку mes
; (индекс в строке содержится в
;регитсре si)
inc si ; увеличение индекса строки на 1
inc al ; увеличение кода символа на 1
loop f1 ; содержимое регистра cx
;уменьшается на 1, если в сх –
;не 0, то переход на метку f1
mov ah,40h ; функция вывода на устройство
;или в файл
mov bx,1 ; вывод на экран
mov cx,128 ; число выводимых байт
mov dx,offset mes ; выводимое сообщение находится
;по адресу ds:dx
int 21h ; прерывание, функция
; прерывания находится в
; регистре ah
mov ax,4c00h ; функция завершения работы
; программы с кодом завершения
int 21h ; прерывание, функция
; прерывания находится в
; регистре ah
mypr endp
cseg ends
; сегмент данных
dseg segment
mes db 128 dup('~')
dseg ends
; сегмент стека
sseg segment
dw 30 dup(?)
TOS label word
sseg ends
end mypr
Задание 3 (Программа 3)
text segment 'code'
assume cs:text, ds:data
begin:
MOV AX, data
MOV DS,AX
MOV cx, 10
f1: MOV AH,09h
MOV DX, offset metka
INT 21h
LOOP f1
MOV AX,4C00h
INT 21h
text ends
data segment
metka db "hello,World!",0dh,0ah,"$"
data ends
end begin
Результаты тестирования
Задание 1 (Программа 1)
Нажимая на кнопки получаем:
Наз. Кнопки. | Результат сообщения. |
SysInfo | Размер страницы: 4096 байт Процессор: 0 Зарезервировано: 0 Количество процессоров: 4 Маска активного процессора: 15 Тип процессора: 586 Гранулярность выделения ресурсов: 65536 Архитектура процессора: 6 Уровень архитектуры процессора: 10759 |
GlobalMemorySatus | Загружено памяти: 36 Всего физическая память: 4201725952 байт Доступная физическая память: 2663731200 байт Общий размер страничного файла: 4294967295 байт Доступный размер страничного файла: 4294967295 байт Общий размер виртуальной памяти: 2147352576 байт Доступный размер виртуальной памяти: 2075938816 байт |
VirtualQuery | Без ввода виртуального адреса выходит ошибка: «Введите виртуальный адрес». Базовый адрес: 0 Адрес размещения: 0 ВАП зарезервировано Размер региона: 65536 байт Состояние ВАП: MEM_FREE Атрибут защиты физ.памяти: PAGE_NOACCESS |
VirtualAlloc | Загружено памяти: 36 байт Всего физическая память: 4201725952 байт Доступная физическая память: 2648408064 байт Общий размер страничного файла: 4294967295 байт Доступный размер страничного файла: 4294967295 байт Общий размер виртуальной памяти: 2147352576 байт Доступный размер виртуальной памяти: 2075938816 байт |
VirtualFree | Выбираем защиту и изменилась только одна строчка: «Доступная физическая память: 2646986752 байт» |
VirtualProtect | Изменилось строчка: «Доступная физическая память: 2652839936 байт» |
Свободные регионы |
Задание 2 (Программа 2)
Задание 3 (Программа 3)
Контрольные вопросы
- Чему в настоящий момент равна гранулярность резервирования регионов адресного пространства для всех платформ Windows?
Структура SYSTEM_INFO. Наименование поля: dwAllocationGranularity;
Описание поля: Гранулярность резервирования регионов адресного пространства. В настоящий момент равно 64Кб для всех платформ Windows.
2. Каким образом при выделении виртуальной памяти указать, что операционная система может выделить память в любой свободной области виртуального адресного пространства?
Функция VirtualAlloc – резервирование региона в адресном пространстве.
Функция имеет следующий вид:
function VirtualAlloc(lpvAddress: Pointer; dwSize, flAllocationType, flProtect: DWORD): Pointer; stdcall;
Таблица параметров.
Наименование параметра | Описание |
lpvAddress | Адрес памяти, указывающий, где именно система должна зарезервировать адресное пространство. Если в качестве этого параметра указать nil, то операционная система сама выберет адрес резервируемого региона в адресном пространстве данного процесса. |
dwSize | Размер резервируемого региона в байтах |
flAllocationType | Сообщает системе, что необходимо сделать (зарезервировать регион или передать физическую память региону). Если требуется только зарезервировать регион без передачи ему физической памяти указывается ключ MEM_RESERVE. Для передачи физической памяти региону указывается ключ MEM_COMMIT. |
flProtect | Атрибут защиты, присваиваемый региону |
Функция VirtualAlloc возвращает виртуальный адрес региона. Если операционная система не сумеет найти в адресном пространстве подходящую область или не сумеет передать ей физическую память, то функция возвращает nil.
- Сколько байт виртуальной памяти будет выделено, если в функции VirtualAlloc в поле «Размер резервируемого региона в байтах» указать число 7000 байт?
Будет выделено: 8192 байта.
4. Объясните алгоритм преобразования виртуального адреса в физический?
Виртуальный адрес делится на номер виртуальной страницы и сдвиг. Номер страницы служит в качестве индекса в таблице страниц. По записи в таблице страниц находится номер физического блока, данный номер присоединяется к старшим разрядам смещения, заменяя, номер виртуальной страницы и формируется физический адрес.
5. Можно ли изменить атрибуты защиты сразу нескольких страниц виртуальной памяти?
Да, если страницы смежные, и они были зарезервированы одним вызовом VirtualAlloc.
Вывод
Программа реализована в среде Delphi 7, работает корректно, ошибок не обнаружено. Программа выполнена в соответствии с техническим заданием. Изучили основные функции ядра kernel32.dll для работы с виртуальной памятью. Рассматриваемые в данной лабораторной работе функции позволяют: получить информацию о состоянии системной памяти и виртуального адресного пространства любого процесса; напрямую резервировать регион адресного пространства; передавать зарезервированному региону физическую память; освобождать регионы адресного пространства; изменять атрибуты защиты страниц виртуальной памяти.