Как преобразовать физический адрес cr3 в линейный при страничной адресации? Или вообще как преобразовать линейный адрес в физический адрес не используя всякие там API операционной системы.
Что значит 'физический адрес cr3'? В CR3 как раз таки и хранится физический адрес. В общем, схема примерно такая: 1. Эффективный адрес складывается с базовым адресом из дескриптора сегмента -- получается линейный адрес. 2. Если включено страничное преобразование, то линейный адрес условно разбивается на 3 части: 1. Биты 0-11 -- адрес байта в странице. 2. Биты 12-21 -- при преобразовании сдвигаются влево на 2 бита, и используется как индекс в таблице сраниц второго уровня (PTE). 3. Биты 22-31-- при преобразовании сдвигаются влево на 2 бита, и используется как индекс в таблице сраниц первого уровня (PDE). В итоге "старшая" из трех частей выбирает нужную запись PDE, которая адресует таблицу второго уровня, средняя, в свою очередь, выбирает в таблице второго уровня нужную запись PTE. Из выбранной PTE берутся старшие 20 бит подставляются в старшие 20 бит линейного адреса. Все это может сопровождаться кэшированием и исключениями . Подробности в мануалах.
Сама по себе постановка задачи странновата - OS может как угодно разнести физические адреса в линейные, т.е. без исследования таблиц трансляции самой OS сделать ничего нельзя, но есть и такой прикол - извлеченный из первой таблицы (Page Directory) _физический_ адрес невозможно применить для дальнейшего изучения (Page Table). Я писал статейку на эту тему (физ. адреса в 98), может быть она поможет.
Не знаю уровня но следующий код запущенный по рингом 0 делает то, то ты хочешь Код (Text): ;----------------------------------------------------------------------------¬ ;¦ GetCR3LogicalAdr: !!! меняет ebp ¦ ;¦ Выход: ¦ ;¦ esi - логический адрес соответствующий физическому CR3 ¦ ;¦ ebx - логический указатель на IDT. ¦ ;L---------------------------------------------------------------------------- xDT STRUC limit dw ? base dd ? xDT ENDS GetCR3LogicalAdr: call GetDataSel jz GLACR3Label6 push ds push esp push ss mov ds,eax mov edx,ss sub esp,6 sgdt [esp] add edx,[esp.base] mov bl,[edx+4] ; BASE 23:16 mov bh,[edx+7] ; BASE 31:24 shl ebx,10h mov bx,[edx+2] ; BASE 15:00 mov ss,eax ; 0 база add esp,ebx ; коректировка esp sidt [esp] mov ebx,[esp.base] add esp,6 push L [ebx+(14*8)] push L [ebx+((14*8)+4)] mov eax,cr4 ; если не сбростить push eax ; то вход таблицы страниц and al,7Fh ; будет кэшироваться и mov cr4,eax ; бит A изменяться не будет call GLACR3Label1 ; Тут будет перехват INT 0E - ошибка страницы ; Один из ключевых моментов программы. Поскольку уровень привелегий ; не изменяется то в стеке будет: ; esp+00 -> Код ошибки ; esp+04 -> Адрес возврата ; esp+08 -> Сегмент возврата ; esp+0Ch -> Флаги ; esp+10h = старый esp INT0E: add esp,10h jmp GLACR3Label3 GLACR3Label1: pop ax push word ptr 8E00h db 66h push cs push ax mov eax,esp shr eax,(10+12-2) and al,0FCh xchg eax,esi cli pop L [ebx+(14*8)] pop L [ebx+((14*8)+4)] GLACR3Label2: mov al,[esi] and al,00100011b cmp al,00100011b jnz GLACR3Label3 mov eax,cr3 ; сброс TLB mov cr3,eax xor byte ptr [esi], 00100000b ; остальные не определены mov eax,cr3 ; сброс TLB mov cr3,eax test byte ptr [esi],00100000b ; не ПЗУ ли jnz GLACR3Label3 mov eax,cr3 ; сброс TLB mov cr3,eax mov eax,[esp] ; доступ и проверка test byte ptr [esi],00100000b ; бита A=1 (доступ осуществлен) jz GLACR3Label4 test byte ptr [esi],10000000b jnz GLACR3Label5 ; страница 2 или 4 Мб push L [esi] and byte ptr [esi], 10111111b mov eax,cr3 ; сброс TLB mov cr3,eax mov eax,[esp] ; доступ и проверка mov [esp],eax test byte ptr [esi],01000000b ; бита D=1 (проведена запись) pop L [esi] jnz GLACR3Label3 ; это не каталог jmp GLACR3Label5 GLACR3Label4: xor byte ptr [esi], 00100000b ; восстановление GLACR3Label3: add esi,1000h jnc GLACR3Label2 GLACR3Label5: pop eax mov cr4,eax pop L [ebx+((14*8)+4)] pop L [ebx+(14*8)] pop edx pop eax mov ss,edx mov esp,eax pop ds and esi,0FFFFF000h GLACR3Label6: retn
Я имею ввиду следующее: 1 На момент считывания cr3 страничная адресация включена. 2 В cr3 физический адресс(не линейный!!). 3 Следовательно в моей проге этот адрес будет трактоваться как линейный и бутет преобразовываться согласно страничной трансляции. 4 И это не даёт возможности считать каталог. Теперь понятно? PROFi за код спасибо, попробую разобраться.
z0mailbox Вообще то хочу написать операционную систему. А что за тест, ты о чём. Лучше бы по делу что нибудь сказал.
Да вроде преобразовать в общем случае не получиться - просто тебе надо будет формировать таблицу pde и начало массива таблиц pte по заранее известным ЛИНЕЙНЫМ адресам.