Я написал пример программы которая включает режим PAE (запускается из под DOS и переключается в защищённый режим). Она проецирует три виртуальных адреса 0B8000h, 0FF000000h, 0EE000000h на физический адрес 0B8000h и выводи три раза один и тот же текст, по этим трём адресам. За формирование адресов отвечает одна процедурка которой я передаю виртуальный адрес и физический, а она создаёт нужные структуры Вот кусок кода который формирует адреса, включает страничную адресацию и выводит сообщения (самое важное это процедурка create_VirtAddressPAE) (FASM) Code (Text): PAGE_DIRECTORIES_POINTERS_TABLE_BASE_ADDRESS equ 01A00000h PAGE_DIRECTORIES_TABLE_BASE_ADDRESS equ 01A01000h PAGE_TABLES_BASE_ADDRESS equ 01A10000h TABLES_END equ 02210000h START_CODE: xor eax, eax mov edi, PAGE_DIRECTORIES_POINTERS_TABLE_BASE_ADDRESS mov ecx, (TABLES_END - PAGE_DIRECTORIES_POINTERS_TABLE_BASE_ADDRESS)/4 rep stosd mov eax, START_CODE mov ebx, eax call create_VirtAddressPAE mov eax, 0B8000h mov ebx, eax call create_VirtAddressPAE mov eax, 0FF000000h mov ebx, 0B8000h call create_VirtAddressPAE mov eax, 0EE000000h mov ebx, 0B8000h call create_VirtAddressPAE mov eax, PAGE_DIRECTORIES_POINTERS_TABLE_BASE_ADDRESS mov cr3, eax mov eax, cr4 or eax, 32 mov cr4, eax mov eax, cr0 or eax, 80000000h mov cr0, eax ;--------------------PAE PAGING ENABLED------------------------- mov esi, message1 mov edi, 0B8000h mov ecx,18 rep movsb mov esi, message2 mov edi, 0FF000012h mov ecx, 18 rep movsb mov esi, message3 mov edi, 0EE000024h mov ecx, 18 rep movsb jmp $ message1 db "152535455565758595" message2 db "A5d5r5F5F505050505" message3 db "A5d5r5E5E505050505" create_VirtAddressPAE: ; in ; EAX page address ; EBX phys page address pushad and eax, 0FFFFF000h and ebx, 0FFFFF000h mov edi, eax mov esi, ebx shr eax, 30 mov ebx, eax mov ecx, eax ;ebx, ecx, eax index in Page Directories Table shl eax, 3 ; eax = eax*8 add eax, PAGE_DIRECTORIES_POINTERS_TABLE_BASE_ADDRESS ; eax point to entry of Page Directories Table imul ebx, ebx, 512*8 add ebx, PAGE_DIRECTORIES_TABLE_BASE_ADDRESS ; ebx point to Page Directory ;add eax, 4 ;!!!!!---!!! or ebx, 1 mov [eax], ebx ;sub eax, 4 ;!!!---!!! mov eax, edi shl eax, 2 shr eax, 23 mov edx, eax ; edx, eax index in page dir shl eax, 3 ; eax = eax*8 add eax, ebx ; eax point to page dir entry imul edx, ecx imul edx, 512*8 add edx, PAGE_TABLES_BASE_ADDRESS ; edx point to page table ;add eax, 4 ;!!!!!---!!! or edx, 3 mov [eax], edx ;sub eax, 4 ;!!!---!!! mov ebx, edi shl ebx, 11 shr ebx, 23 ; ebx index in page table shl ebx, 3 ; ebx = ebx*8 add ebx, edx ; ebx point to page table entry ;add ebx, 4 ;!!!!!---!!! or esi, 3 mov [ebx], esi .end: popad ret по адресу PAGE_DIRECTORIES_POINTERS_TABLE_BASE_ADDRESS находится таблица указателей на каталоги по адресу PAGE_DIRECTORIES_TABLE_BASE_ADDRESS надодятся четыре каталога по адресу PAGE_TABLES_BASE_ADDRESS находятся таблицы страниц проверяю прогу на машине VirtualBox в общем прога не работает, чего только не пробовал: неполучается Парни, пожалуйста, помогите если не лень кто чем может, ошибка наверняка какая-нибудь глупая....
Хм, странный немного код у тебя. Попробуй заменить на этот: Code (Text): map_addr: and ebx, 0xFFFFF000 mov edx, eax shr eax, 0x1E shl eax, 0x3 add eax, PAGE_DIRECTORIES_POINTERS_TABLE_BASE_ADDRESS mov [eax], PAGE_DIRECTORIES_TABLE_BASE_ADDRESS or 0x1 mov eax, edx shr eax, 0x15 and eax, 0x1FF shl eax, 0x3 add eax, PAGE_DIRECTORIES_TABLE_BASE_ADDRESS mov [eax], PAGE_TABLES_BASE_ADDRESS or 0x1 mov eax, edx shr eax, 0xC and eax, 0x1FF shl eax, 0x3 add eax, PAGE_TABLES_BASE_ADDRESS or 0x1 or ebx, 0x1 mov [eax], ebx ret Я его, правда, не проверял на машине -- только в голове прокрутил, но, вроде, работать должно. Помимо этого, необходимо сбросить очередь команд после выставления бита, отвечающего за страничное преобразование. Т.е. поставь что-то вроде: Code (Text): jmp next next:
неа, не работает этот код, слишком он простой тебя мой код не странный, он сложный, кто разберётся - тот герой
ُУгу, настолько сложный, что аж не работает . Совсем забыл: каждая entry же 8 байт. Соотвественно, должно быть так: Code (Text): map_addr: and ebx, 0xFFFFF000 mov edx, eax shr eax, 0x1E shl eax, 0x3 add eax, PAGE_DIRECTORIES_POINTERS_TABLE_BASE_ADDRESS mov [eax], PAGE_DIRECTORIES_TABLE_BASE_ADDRESS or 0x1 mov [eax + 0x4], 0x0 mov eax, edx shr eax, 0x15 and eax, 0x1FF shl eax, 0x3 add eax, PAGE_DIRECTORIES_TABLE_BASE_ADDRESS mov [eax], PAGE_TABLES_BASE_ADDRESS or 0x1 mov [eax + 0x4], 0x0 mov eax, edx shr eax, 0xC and eax, 0x1FF shl eax, 0x3 add eax, PAGE_TABLES_BASE_ADDRESS or 0x1 or ebx, 0x1 mov [eax], ebx mov [eax + 0x4], 0x0 ret
неа, он тоже на работает! суть проблемы в том что, а нас 4 каталога страниц, поэтому что бы поставить нормальную ссылку на каталог, надо умножить индекс каталога на 512*8 (размер одного каталога) и прибавить к PAGE_DIRECTORIES_TABLE_BASE_ADDRESS для этого у меня и есть код Code (Text): imul ebx, ebx, 512*8 ; в ebx изначально индекс каталога мы его умножаем на 512*8 и сохраняем в ebx add ebx, PAGE_DIRECTORIES_TABLE_BASE_ADDRESS ; теперь в ebx у нас ссылка на контретный каталог страниц аналогичная ситуация с таблицами страниц (их ещё больше!!!!) Code (Text): imul edx, ecx ; в ecx у нас индекс каталога, в edx индекс в этом каталоге страниц и мы их перемножаем imul edx, 512*8 ; мы это число умножаем на размер одной таблицы страниц add edx, PAGE_TABLES_BASE_ADDRESS ; теперь в edx у нас ссылка на конкретную таблицу страниц првильно, он не работает потому что он сложный кстати, првильно ли я включаю страничную адресацию? я сначала выставляю пятый бит в cr4 и потом выставляю последный бит в cr0
Зачем? Старшие 2 бита адреса -- индекс в PDPT. Размер элемента PDPT -- 8 байт. Он содержит физический адрес каталога таблиц. Соотвественно, получив старшие два бита адреса, умножив их на 8 и сложив с базовым физическим адресом PDPT, получим физический адрес элемента PDPT, который содержит физический адрес каталога таблиц: Code (Text): mov edx, eax shr eax, 0x1E shl eax, 0x3 add eax, PAGE_DIRECTORIES_POINTERS_TABLE_BASE_ADDRESS ;теперь еах содержит физический адрес элемента PDPT. ;запишем в него физический адрес каталога таблиц, с установленным битом присутствия ; и обнулим старшие 32 бита элемента. mov [eax], PAGE_DIRECTORIES_TABLE_BASE_ADDRESS or 0x1 mov [eax + 0x4], 0x0 Те же действия надо проделать с оставшейся частью адреса. Нашел у себя опечатку: Code (Text): add eax, PAGE_TABLES_BASE_ADDRESS or 0x1 замени на: Code (Text): add eax, PAGE_TABLES_BASE_ADDRESS
Ну и до кучи на 512*8 множить не стоит. Битовые сдвиги никто не отменял Хотя ошибка ясное дело не в этом...
но каталогов таблиц целых четыре: первый катлог будет по адресу PAGE_DIRECTORIES_TABLE_BASE_ADDRESS, второй каталог будет по адресу PAGE_DIRECTORIES_TABLE_BASE_ADDRESS+1000h, третий каталог будет по адресу PAGE_DIRECTORIES_TABLE_BASE_ADDRESS+2000h и четвёртый каталог PAGE_DIRECTORIES_TABLE_BASE_ADDRESS+3000h, для этого и надо умножать индекс каталога на 512*8 и прибавлять к базе
Неважно, в каком порядке и как располагать таблицы. Их адреса известны тебе заранее. Соотвественно вычислять их не надо. 1. Существует ли физ. адрес 1A00000 и т.п. в вирт. машине? Поддерживает ли Virt. Box PAE? 2. Пробовал ли отлаживать в Bochs? Bochs более подробен в случае возникновения ошибки. 3. Покажи, какой код у тебя получился в итоге (с моей вставкой), или выложи образ для Bochs, который можно запустить.
1. Физический адрес 1A00000 (это район 26 мегабайта) точно есть на вирт. машине т.к. в настройках указано 64 МБ 2. Я как раз и собираюсь использловать Bochs 3. Я не использую Bochs потому что у меня то создаётся прога в форамте MZ для DOS, а как я её помещу в образ? (VirtualBox я просто настроил так чтобы она использовала реальную дисекту отформатированную как загрузочный диск MS-DOS) в общем мне по ходу придётся переписать прогу что бы она являлась загрузчиком чтобы можно было её засунуть в образ. В общем если уже кому-то реально интересна моя проблема, то прикрепляю исходник проги. там 2 файла pm.asm(основной файл) и PM_CODE.ASM (код защищённого режма).
У тебя в исходнике стоит 'add eax, PAGE_TABLES_BASE_ADDRESS or 0x3', в предыдущем посте я писал, что это надо изменить на 'add eax, PAGE_TABLES_BASE_ADDRESS'.
всем спасибо за участие!!!! хоть кто-то попытался помочь..... проблема решилась, я всё таки исправил свою процедурку "создания" виртуального адреса (истина была рядом!) выкладываю её код, восклицательными знаками помечены ключевые строки может кому-нибудь пригодится.... Code (Text): create_VirtAddressPAE: ; in ; EAX page address ; EBX phys page address pushad and eax, 0FFFFF000h and ebx, 0FFFFF000h mov edi, eax mov esi, ebx shr eax, 30 mov ebx, eax mov ecx, eax ;ebx, ecx, eax index in Page Directories Table shl eax, 3 ; eax = eax*8 add eax, PAGE_DIRECTORIES_POINTERS_TABLE_BASE_ADDRESS ; eax point to entry of Page Directories Table shl ebx, 12 add ebx, PAGE_DIRECTORIES_TABLE_BASE_ADDRESS ; ebx point to Page Directory push ebx ; save ebx !!!!!! or ebx, 1 ; set present flag !!!!!! mov [eax], ebx pop ebx ; backup ebx !!!!!!!!! mov eax, edi shl eax, 2 shr eax, 23 mov edx, eax ; edx, eax index in page dir shl eax, 3 ; eax = eax*8 add eax, ebx ; eax point to page dir entry imul edx, ecx shl edx, 12 add edx, PAGE_TABLES_BASE_ADDRESS ; edx point to page table push edx ; save edx !!!!! or edx, 3 ; set present, write, supervisor flags mov [eax], edx pop edx ; backup edx !!!!!!!!! mov ebx, edi shl ebx, 11 shr ebx, 23 ; ebx index in page table shl ebx, 3 ; ebx = ebx*8 add ebx, edx ; ebx point to page table entry or esi, 3 mov [ebx], esi .end: popad ret
Ага. Ребята в теме. Есть вопрос. 1. ВиндаХР использует PAE для предотвращения выполнения данных. 2. Больше 4ГБ физического пространства обрабатывать всеравно не хочет (да и не надо, нет столько у меня, проблемы с дровами и тд и тп). 3. Позволяет создать своп больше чем на 4ГБ. а. Больше ли будет виртуалки? б. Почему можно создать своп на 80ГБ?
Я не специалист по swap'у, но, насколько я понимаю, ничего страшного в большом swap'е нет. Задач-то в ОС много, адресное пространство каждой -- 4 GB. Соответственно, и swap может быть больше чем 4 GB.
если я не ошибаюсь, в Windows СУММА виртуальной памяти ВСЕХ приложениий не считая ядерной и не считая промэпированной не превышает 4 ГБ. Винда не даст приложениям выделить больше.
Ты ошибаешся. Ядерная память общая плюс 2Гб или 3Гб подьзовательского адресного пространства для каждого процесса. Создай 5 процессов и в каждом выдели 1Гб памяти - система ругнётся на нехватку виртуальной памяти и предложит увеличить своп. При согласии своп просто увеличится до ~5Гб и всё. Отказа в выделении никто не получит. PS: эксперимент надо проводить при свопе размещённом на NTFS разделе, на FAT работать не будет т.к. там максимальный размер файла 4Гб - но это ограничение FS а не ОС в целом.
cppasm Ты этот эксперимент реально проводил? Всё было как ты сказал? Тогда я не знаю, что это за версия винды. У меня своп файл мало увеличился, когда было запрошено пятью процессами по 1Г. Двум процессам был дан отказ.
10110111, надо проверить, но мне кажется тоже, что объем доступной памяти ограничивается только объемом оперативы и свопа, возможности защищенного режима позволяют раздавать виртуальную память направо и налево
Я этот эксперимент реально проводил. Ставиш своп в 5 гб и все будет ок, все запросы будут выполнены, но скорость... В этом и смысл PAE