Всем привет! Подскажите, как правильно включить страничный режим ситуация такая: мы в защищенном режиме (режим страничной адресации выключен), выполняющийся код расположен по линейному (физическому) адресу 0x100000. Таблицы страниц настроены и отображают этот код на 0xC0100000. После выставления PG в CR0 и jump-а идет вылет с перезагрузкой Код (Text): ; настройка cr3 и пр ... lgdt [gdtr - OFFSET] ; OFFSET = 0xC0000000, в gdtr линейный адрес GDT уже отображенный, т. е 0xC... mov eax, cr0 or eax, 1 SHL 31 mov cr0, eax jmp far 08h:@F @@: ; физический адрес = 0x100200, в предыдущем jmp смещение = 0xC0100200, селектор = 8 ; сюда не попадаем ... в мануале от Intel прочитал (см. выделенное) изменил gdtr (поле линейного адреса теперь содержит физический адрес (но который можно интерпретировать и как виртуальный (отображается сам в себя))) и подправил таблицы страниц, кроме того подправил jmp Код (Text): jmp far 08h:@F - OFFSET но все равно не работает в чем может быть дело?
http://www.wasm.ru/article.php?article=pipm06 http://www.wasm.ru/article.php?article=pipm09 PS. Maybe +OFFSET, а не -OFFSET?
rei3er Значит не все знаешь. Либо неверно инициализированна карта таблиц страниц... Переключение у меня работает : Код (Text): mov eax,cr0 ;Read CR0. bts eax,31 ;Set PE=1. mov cr0,eax ;Write CR0. db 0ebh,0 ;jmp0 А вообще будте спокойнее и приведите пожалуйсто весь ваш код.
извините, просто действительно непонятно, где ошибка код я конечно привести могу, но сомневаюсь, что кто-то будет в нем разбираться: уж очень он большой
Не совсем понял, зачем в 'lgdt [gdtr - OFFSET]' отнимается OFFSET -- ведь страничное преобразование еще не включено...
в том то и дело если оставить так Код (Text): lgdt [gdtr] то получим а необходим физический адрес, т. е
rei3er Бред. У тебя еще нет страничной адресации... в реальном режиме лин=физ адресу как правило. я делал так : lgdt [pGDT32] ... mydata: pGDT32: dw gdtend-gdt ;GDT лимит dd gdt ;и 32-битная база GDT dd 0 и все работало.
Код (Text): org 0x100000 + OFFSET start: ; на самом деле этот код при выполнении находится по адресу 0x00000500 mov esi, 0x00000500 mov edi, 0x100000 mov ecx, KSIZE / 4 ; KSIZE = 0x3000 cld rep movsd mov eax, entry_32 - OFFSET jmp eax ; переходим на 0x100000 + (entry_32 - start) entry_32: mov eax, [OPTIONS_SEG SHL 4 + MEM_SIZE_OFFSET] ; OPTIONS_SEG = 0x9000 (получаем общее количество памяти в системе в байтах (тут все правильно!!)) shr eax, 7 and eax, (NOT 0) SHL 5 ; размер всех блоков по 32 байта, каждый из которых описывает физическую страницу памяти add eax, 0x100000 + KSIZE ; физический адрес начала таблиц страниц mov ebx, eax and eax, NOT ((NOT 0) SHL 12) jz @F ; если адрес выравнен по размеру страницы ; иначе выравниваем sub eax, 4096 neg eax add ebx, eax @@: xor edx, edx mov ebp, page_dir - OFFSET + (OFFSET SHR 22 - 1) SHL 2 ; начинаем с 768 элемента каталога страниц @@1: mov eax, 3 ; установить P и W биты or eax, ebx ; 20 старших бит физического адреса таблицы страниц add ebp, 4 mov dword [ebp], eax ; установить PDE (здесь ss = ds, потому можно использовать [ebp]) @@2: mov eax, 3 or eax, edi ; 20 старших бит физического адреса реальной страницы mov dword [ebx], eax ; установить PTE add ebx, 4 add edi, 4096 cmp edi, ebx jae @F test ebx, NOT ((NOT 0) SHL 12) jnz @@2 ; текущая таблица страниц заполнена не до конца jmp @@1 ; переходим к следующему элементы каталога страниц @@: lgdt [gdtr - OFFSET] mov eax, page_dir - OFFSET mov cr3, eax mov eax, cr0 or eax, 1 SHL 31 mov cr0, eax jmp 08h:@F @@: ... gdtr: dw BOOT_GDT_TABLE - 1 dd gdt gdt: dq 0x0000000000000000 dq 0x00CF98000000FFFF ; 32-ух битный код dq 0x00CF92000000FFFF ; 32-ух битные данные BOOT_GDT_TABLE = $ - gdt align 4096 page_dir: db 4096 dup(0)
во-первых, у меня защищенный режим во-вторых, потому как страничная адресация не включена, мне и нужен физический адрес gdtr, т. е 0x00100300, а не 0xC0100300, который зашивается в команде Код (Text): lgdt [gdtr]
rei3er Хм.. я конечно могу посмотреть в чем проблема. Но сразу скажу, если запускаешь под Досом, то зачем такой org делать (сделал бы 100h) далее - эти привязки к адресам в начале кода .. ты не умеешь получать дельта смещение ?.. и эти оффсеты.. В общем эти замечания при первом взгляде. Конкретно попозже сообщу... а может кто до меня успеет.
TermoSINteZ я привел часть кода, причем сильно упрощенную DOS и пр. вообще не причем: идет загрузка через boot-сектор (свой) мне нужно, чтобы код работал и в страничном режиме и в обычном защищенном без страничного для этого сделан org = 0xC0100000 любой физический адрес в пределах кода/данных отображается на виртуальный с использованием OFFSET, т. е Код (Text): lgdt [gdtr - OFFSET] ; ТУТ СТРАНИЧНЫЙ РЕЖИМ НЕ ВКЛЮЧЕН, ПОЭТОМУ В КОМАНДУ ЗАШИТ АДРЕС 0x00100300 mov eax, page_dir - OFFSET mov cr3, eax mov eax, cr0 or eax, 1 SHL 31 mov cr0, eax jmp 08h:@F @@: lgdt [gdtr] ; ТУТ СТРАНИЧНЫЙ РЕЖИМ ВКЛЮЧЕН, ПОЭТОМУ НУЖЕН АДРЕС 0xC0100300 gdtr: dw BOOT_GDT_TABLE - 1 dd gdt gdt: dq 0x0000000000000000 dq 0x00CF98000000FFFF ; 32-ух битный код dq 0x00CF92000000FFFF ; 32-ух битные данные BOOT_GDT_TABLE = $ - gdt align 4096 page_dir: db 4096 dup(0)
rei3er Теперь понятно как все работает Мнеб глянуть полный код... Чтоб можно было протестить . А без него скажу - И еще - как ты определяешь, что код не доходит до того места, ты можешь хотяб посмотреть какое происходит исключение. Я почему-то уверен , что дело в таблицах страниц. Попробуй их по началу просто отобразить линейно... одна база кода , одна база данных, одна база стека (с 0 адреса на 4 гига) и проверить . правильно ли заполнено. Например записав в видеопамять что нибудь.
Код (Text): ; если тут вставить, что-нибудь, например запись в видеопамять, то все ОК ; mov word [0xB800 SHL 4], 0x0F30 mov eax, cr0 or eax, 1 SHL 31 mov cr0, eax jmp 08h:@F @@: ; если сюда вставить запись в видеопамять, то ничего не выводится (кроме того идет reboot) проверял на VMWare говорит Kernel Stack Fault причем тут стек, вообще непонятно...
rei3er А что еслид объявишь дескриптор описатель стека , и инициализируешь селектор ss. Может будет другая ошибка ?
не думаю, стек у меня вообще не используется, а VMWare по-моему для любой ошибки, которая приводит к перезагрузке пишет Kernel Stack Fault
Тогда я бы поставил QEMU и посмотрел бы ошибку .. либо сделал бы обработчик исключений, точнее обработчики прерываний и нарушений и выводил бы на экран код ошибки ... (он в стеке должен быть)
Вообще, лучше всего для таких целей подходит Bochs -- у него и отладчик есть и лог достаточно подробный. А VMWare в этом вопросе верить нельзя -- она на все что угодно говорит "Kernel Stack Fault". Кстати, полного кода действительно не хватает.