Функция 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)

 

Контрольные вопросы

  1. Чему в настоящий момент равна гранулярность резервирования регионов адресного пространства для всех платформ 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.

 

  1. Сколько байт виртуальной памяти будет выделено, если в функции VirtualAlloc в поле «Размер резервируемого региона в байтах» указать число 7000 байт?

 

Будет выделено: 8192 байта.

4. Объясните алгоритм преобразования виртуального адреса в физический?

 

Виртуальный адрес делится на номер виртуальной страницы и сдвиг. Номер страницы служит в качестве индекса в таблице страниц. По записи в таблице страниц находится номер физического блока, данный номер присоединяется к старшим разрядам смещения, заменяя, номер виртуальной страницы и формируется физический адрес.

 

5. Можно ли изменить атрибуты защиты сразу нескольких страниц виртуальной памяти?

 

Да, если страницы смежные, и они были зарезервированы одним вызовом VirtualAlloc.

 

Вывод

 

Программа реализована в среде Delphi 7, работает корректно, ошибок не обнаружено. Программа выполнена в соответствии с техническим заданием. Изучили основные функции ядра kernel32.dll для работы с виртуальной памятью. Рассматриваемые в данной лабораторной работе функции позволяют: получить информацию о состоянии системной памяти и виртуального адресного пространства любого процесса; напрямую резервировать регион адресного пространства; передавать зарезервированному региону физическую память; освобождать регионы адресного пространства; изменять атрибуты защиты страниц виртуальной памяти.