помогите люди доскакально разобраться в страничной адресации
Проблема вообщем-то вот в чем.
имею отрывок исходника:
get_phys_mem_size proc near
; Вычисляет размер физической памяти, установленной в компьютере
; Возврат: EAX = размер памяти в байтах
push bx
push ecx
push edx
push ebp
push es
push edi
mov ax,All_mem_sel ; Для проверки памяти мы будем
mov es,ax ; использовать сегмент, описывающий
; всю память.
mov bx,Page_Directory_adr ; DS:BX указывает на
; начало каталога страниц.
add bx,1000h + 256 * 4 ; А теперь - на первую страницу
; второго мегабайта памяти в первой
; таблице страниц.
mov edx,12345678h ; Это тестовое значение, которое
; мы будем записывать и затем
; считывать из памяти.
mov ebp,1024 * 1024 * 2 ; В EBP будет находится адрес,
; с которого мы будем проверять
; память.
gpms_1:
; Подготавливаем в первой определённой таблице страниц 256 элементов PTE,
; начиная с 256. Они будут описывать второй мегабайт адресного пространства.
; Эти PTE мы отобразим не один мегабайт физической памяти, начиная с адреса
; в EBP.
mov edi,1024 * 1024
mov eax,ebp
mov cx,256
mov al,3 ; Записывая в AL 3, мы тем самым устанавливаем
; биты 0 и 1 этого регистра. Когда мы запишем EAX
; на место какого-либо элемента PTE в таблице
; страниц, то эти биты определят этот элемент как
; присутствующий (бит P=1) с разрешённым доступом
; по чтению записи (бит R/W=1).
; Записываем 256 элементов PTE:
gpms_2:
mov [ bx ],eax
add eax,1000h
add bx,4
loop gpms_2
mov eax,cr3 ; Перегружаем значение CR3. Это вызовет
mov cr3,eax ; сброс буферов TLB и заставит процессор
; использовать обновлённые значения из
; изменённой нами таблицы страниц.
jmp $+2 ; Выполняя команду перехода, мы сбрасываем
; конвейер команд процессора, заставляя его заново
; считывать текущую часть кода и очистить результаты
; всех спекулятивно выполненных команд. Для нас это
; гарантия того, что процессор будет работать с
; обновлённой таблицей страниц.
sub bx,256 * 4 ; Возвращаем указатель на 256-й элемент
; PTE в таблице страниц.
mov cx,256
; Тестируем память:
gpms_3:
mov eax,edx ; EAX = 12345678h.
xchg eax,es:[ edi ] ; Пара команд XCHG выполнит "не
xchg eax,es:[ edi ] ; разрушающий" контроль памяти.
add edi,1000h
cmp eax,edx ; Если было прочитано то же значение, что
; и записано, значит текущая страница памяти
; отображена на ОЗУ.
jne gpms_4 ; Иначе - мы дошли до конца ОЗУ.
loop gpms_3
add ebp,1000h * 256 ; Здесь меняется адрес физической
; памяти, на который будет отображён
; следующий мегабайт.
jmp gpms_1
gpms_4:
mov eax,ebp
add eax,edi
sub eax,1000h * 257 ; EAX содержит адрес последней
; реально присутствующей физической
; страницы памяти, это и есть размер
; физической памяти.
; Очистка элементов PTE, отображённых на второй мегабайт (т.е. возврат
; таблицы страниц в первоначальное состояние.
mov edx,eax
mov ax,ds
mov es,ax
mov di,Page_Directory_adr
add di,256 * 4
mov cx,256
xor eax,eax
cld
rep stosd
mov eax,edx ; EAX = размер физической памяти в байтах.
pop edi
pop es
pop ebp
pop edx
pop ecx
pop bx
ret
endp
Выдрал с одного сайта.
Так вот можете ли вы мне по подробнее объяснить что да как происходит.
Особенно:
mov ax,All_mem_sel ; Для проверки памяти мы будем
mov es,ax ; использовать сегмент, описывающий
; всю память.
mov bx,Page_Directory_adr ; DS:BX указывает на
; начало каталога страниц.
add bx,1000h + 256 * 4 ; А теперь - на первую страницу
; второго мегабайта памяти в первой
; таблице страниц.
mov edx,12345678h ; Это тестовое значение, которое
; мы будем записывать и затем
; считывать из памяти.
mov ebp,1024 * 1024 * 2 ; В EBP будет находится адрес,
; с которого мы будем проверять
; память.
gpms_1:
; Подготавливаем в первой определённой таблице страниц 256 элементов PTE,
; начиная с 256. Они будут описывать второй мегабайт адресного пространства.
; Эти PTE мы отобразим не один мегабайт физической памяти, начиная с адреса
; в EBP.
mov edi,1024 * 1024
mov eax,ebp
mov cx,256
mov al,3 ; Записывая в AL 3, мы тем самым устанавливаем
; биты 0 и 1 этого регистра. Когда мы запишем EAX
; на место какого-либо элемента PTE в таблице
; страниц, то эти биты определят этот элемент как
; присутствующий (бит P=1) с разрешённым доступом
; по чтению записи (бит R/W=1).
; Записываем 256 элементов PTE:
gpms_2:
mov [ bx ],eax
add eax,1000h
add bx,4
loop gpms_2
mov eax,cr3 ; Перегружаем значение CR3. Это вызовет
mov cr3,eax ; сброс буферов TLB и заставит процессор
; использовать обновлённые значения из
; изменённой нами таблицы страниц.
jmp $+2 ; Выполняя команду перехода, мы сбрасываем
; конвейер команд процессора, заставляя его заново
; считывать текущую часть кода и очистить результаты
; всех спекулятивно выполненных команд. Для нас это
; гарантия того, что процессор будет работать с
; обновлённой таблицей страниц.
sub bx,256 * 4 ; Возвращаем указатель на 256-й элемент
; PTE в таблице страниц.
mov cx,256
; Тестируем память:
gpms_3:
mov eax,edx ; EAX = 12345678h.
xchg eax,es:[ edi ] ; Пара команд XCHG выполнит "не
xchg eax,es:[ edi ] ; разрушающий" контроль памяти.
add edi,1000h
cmp eax,edx ; Если было прочитано то же значение, что
; и записано, значит текущая страница памяти
; отображена на ОЗУ.
jne gpms_4 ; Иначе - мы дошли до конца ОЗУ.
loop gpms_3
add ebp,1000h * 256 ; Здесь меняется адрес физической
; памяти, на который будет отображён
; следующий мегабайт.
jmp gpms_1
И подкиньте какой-нибудь исходник на асме где обильно используется страничная адресация с коментами.
Спасибо заранее
И в чем проблема?
; начало каталога страниц.
add bx,1000h + 256 * 4 ; А теперь - на первую страницу
; второго мегабайта памяти в первой
; таблице страниц.
mov edx,12345678h ; Это тестовое значение, которое
; мы будем записывать и затем
; считывать из памяти.
mov ebp,1024 * 1024 * 2 ; В EBP будет находится адрес,
; с которого мы будем проверять
; память.
gpms_1:
; Подготавливаем в первой определённой таблице страниц 256 элементов PTE,
; начиная с 256. Они будут описывать второй мегабайт адресного пространства.
; Эти PTE мы отобразим не один мегабайт физической памяти, начиная с адреса
; в EBP.
mov edi,1024 * 1024
mov eax,ebp
mov cx,256
mov al,3 ; Записывая в AL 3, мы тем самым устанавливаем
; биты 0 и 1 этого регистра. Когда мы запишем EAX
; на место какого-либо элемента PTE в таблице
; страниц, то эти биты определят этот элемент как
; присутствующий (бит P=1) с разрешённым доступом
; по чтению записи (бит R/W=1).
; Записываем 256 элементов PTE:
gpms_2:
mov [ bx ],eax
add eax,1000h
add bx,4
loop gpms_2
mov eax,cr3 ; Перегружаем значение CR3. Это вызовет
mov cr3,eax ; сброс буферов TLB и заставит процессор
; использовать обновлённые значения из
; изменённой нами таблицы страниц.
jmp $+2 ; Выполняя команду перехода, мы сбрасываем
; конвейер команд процессора, заставляя его заново
; считывать текущую часть кода и очистить результаты
; всех спекулятивно выполненных команд. Для нас это
; гарантия того, что процессор будет работать с
; обновлённой таблицей страниц.
sub bx,256 * 4 ; Возвращаем указатель на 256-й элемент
; PTE в таблице страниц.
mov cx,256
; Тестируем память:
gpms_3:
mov eax,edx ; EAX = 12345678h.
xchg eax,es:[ edi ] ; Пара команд XCHG выполнит "не
xchg eax,es:[ edi ] ; разрушающий" контроль памяти.
add edi,1000h
cmp eax,edx ; Если было прочитано то же значение, что
; и записано, значит текущая страница памяти
; отображена на ОЗУ.
jne gpms_4 ; Иначе - мы дошли до конца ОЗУ.
loop gpms_3
add ebp,1000h * 256 ; Здесь меняется адрес физической
; памяти, на который будет отображён
; следующий мегабайт.
jmp gpms_1
Все бы ничего,но почему в edi всегда 1024*1024 при проверке следуещего мегабайта? ведь страницы сюда не отображены?
Я вот этого что-то не догоняю.
Объясните подробно, плиз.
Я разобрался всё-таки