Добрый день, пытаюсь переключиться в защищенный режим, но переход на pmode_entry не происходит, комп перезагружается. Подскажите что не так? Код (Text): ;=============== REAL MODE =============; use16 start: mov ax, cs mov ds, ax mov es, ax ; clear screen ; mov ax, 3 int 10h ;enable A20 mov ax, 0x2401 int 0x15 ; включать a20 пробовал разными способами, может в этом дело? jnc err1 ; тут CF = 0 как бы все ок ; disable interrupts cli in al, 70h or al, 80h out 70h, al ; load GDT register lgdt fword [GDTR] ; enable protected mode mov eax, cr0 or al, 1 mov cr0, eax jmp 00001000b:pmode_entry err1: ;ошибка открытия а20 jmp $ gdt: dw 0, 0, 0, 0 db 0xFF db 0xFF db 0x00 db 0x00 db 0x00 db 10011010b db 11001111b db 0x00 db 0xFF db 0xFF db 0x00 db 0x00 db 0x00 db 10010010b db 11001111b db 0x00 GDT_size equ $-gdt GDTR dw GDT_size-1 dd gdt ;=============== PROTECTED MODE =============; use32 pmode_entry: jmp $ ; сюда не доходит mov ax, 00010000b mov ds, ax mov es, ax ; enable interrupts in al, 70h and al, 7Fh out 70h, al sti jmp $ mov edi, 0xB8000 mov byte[edi], 'A' jmp $
Попробуй так: Код (Text): start: xor ax, ax mov ds, ax ... jmp fword 8:pmode_entry Такое открытие линии A20 почти не используется из-за слабой поддержки данной функции в BIOS. Запрещать NMI лучше так: Код (Text): mov al, 1???????b out 70h, al in al,71h Эта последовательность команд является более законченной, чем твой вариант.
GLEB 0-ой дескриптор = 0. К нему обращаться вообще ни как нельзя. 1-ый дескриптор для GDT, любое обращение к нему кроме чтения дескриптора процессором - #GP 2-ой дескриптор для IDT, но на практике от может читаться/писаться и выполняться (на борще) 3..8191-ый дескрипторы для системы.
Что за бред? Какие дескрипторы GDT и IDT!? Нулевой дескриптор - NULL. К нему обращаться нельзя. Все остальные заполняйте как хотите, но для PM вам потребуется как минимум один дескриптор сегмента данных и один дескриптор для сегмента кода. IDT и GDT не требуют для себя отдельных дескрипторов. Главное, чтобы они были доступны в текущем линейном адресном пространстве (об этом надо думать только при включённой страничной адресации). При этом совсем не обязательно, чтобы к ним можно было даже обратиться (например, они лежат вне всех сегментов программы из GDT) из кода.
GLEB, я извиняюсь за возможно допущенную неточность. Как запускается твоя программа (что это исполняемый файл com, exe, просто бинарный файл или код бутсектора)?
Вроде разобрался у меня этот код загружался в 0x7E0:0, поэтому нужно было вычислять адреса всех меток приведенный код тоже работает если загружен в 0:0x7E00 и с директивой org 0x7E00 Phantom_84 теперь хочу уточнить по поводу A20 она получается включена по умолчанию? если ничего не делать, 20й бит адесной шины не сбрасывается, проверял и на виртуалке и на реальном железе Как правильно ее включать? Код (Text): in al, 92h or al, 2 out 92h, al Кто-то говорит, что данные код может не сработать на новом железе это не мой вариант ), код запрета NMI взят со статьи о защищенном режиме c форума ) а что не закончено? имеется ввиду обращение к порту in al,71h ?
Забей на тех кто это пишет. 90% рынка ПК это intel. Intel это не только ЦП, но и набор чипов для материнок. А она пока поддерживает совместимость. Вот когда в сети появятся данные, что такой-то такой-то производитель не поддерживает. И будет известно ID данного железа. А пока ID нет это всё на воде вилами писано.
Раньше как то не задумывался. Сейчас подумал. Мы же выбираем первой командой ЧИП, а значит просто обязаны прочитать данные? И так наверно надо делать со всем устарелым и не очень железом.
Сомневаюсь. Хотя в частном случае такое возможно. Как ты проверяешь открытость адресной линии? А кто-то говорит, что этот код прежде всего может не сработать на старом железе. Хороший вопрос. Я использую открытие через контроллер клавиатуры совместно с этим способом (с собой сейчас исходников нет, попробую поискать в сети). Функцию 24h не использую. Когда-то пробовал это делать, но быстро понял, что это бесперспективно. Да. Если в дальнейшем понадобится обращаться к CMOS, то могут возникнуть проблемы.
Я тоже какое-то время не задумывался над этим. Но потом где-то случайно подсмотрел этот вариант и задумался ))) Перед in al,71h возможно имеет смысл выполнить небольшую задержку.
Код (Text): mov byte[1000000000000000000000b], 65 ; пишем по адресу 2097152 букву A mov byte[1100000000000000000000b], 66 ; пишем по адресу 3145728 букву B mov al, byte[1000000000000000000000b] ; читаем mov dl, byte[1100000000000000000000b] mov byte[0xB8000], al ; выводим в видеопамять mov byte[0xB8002], dl по умолчанию на экране AB если отключить A20 этим кодом: Код (Text): in al, 92h and al, 0FDh out 92h, al то на экране BB как я понимаю из-за сброса 20-го бита запись происходит в 1000000000000000000000 а не 1100000000000000000000 в итоге B затирает А
Лучше использовать не 3-й и 4-й мегабайт, а 1-й и 2-й. Также твой порядок обращения к памяти один из худших вариантов в плане противодействия кэшированию данных.
Phantom_84 А почему лучше первый и второй? Если A20 не включена, то 20 бит будет сброшен в любом случае (адресе) или нет? Ты имеешь ввиду то, что я записал данные и тут же их прочитал, а в реальную память они так и не попали и остались в кэше? Согласен, но по идее в данном случае результат должен быть одинаков, хоть с кэшем хоть без. Для чистоты эксперимента, отключал кэш Код (Text): mov eax, cr0 or eax, 040000000h mov cr0, eax wbinvd Взято с исходников Memtest86. Результат тот же.
на всем железе которое сертифицировано под windows(а биосы обычно сертифицируют) открытие A20 через 92h порт будет работать. у них в стандартах Legacy pnp и PC98... описан этот порт. и все порты до 100h останутся стандартными) скорее ps/2 уберут. они и так не везде есть. только в эмуляции(если не включена).
Закрытие "линии" может быть реализовано таким образом, что запрещается доступ ко всей памяти выше первого мегабайта, а не только к "четным" мегабайтам. Т.е. при закрытой "линии" обращение к 3-му и 4-му мегу может приводить к обращению к первому мегу. К тому же при использовании 1-го и 2-го мега можно выполнять проверку, оставаясь в RM (как у меня это реализовано). Да. Это уже интересно. Приведенный код возьму на заметку. Я не утверждаю, что у тебя линия изначально закрыта, а детект дает неправильные результаты. Просто для надежности детект нужно сделать максимально достоверным. Жалко, что у меня нет с собой исходников (я сейчас нахожусь в другом городе). Если не ошибаюсь (давно это было), при включении линии A20 я первым делом вызывал процедуру проверки, а значит я тоже допускал возможность открытости линии изначально. В целом алгоритм примерно такой: - проверка; - попытка открытия через контроллер клавиатуры; - проверка; - попытка открытия через порт 92h; - проверка. Для первого способа на wiki osdev.ru есть код, который претерпел не слишком много изменений относительно моего оригинального кода (если не ошибаюсь, у меня в оригинале было xor cx,cx, а не mov cx,0FFFFh , комментарии тоже скорее всего не мои). Для второго способа на wiki код не мой. У меня вроде бы перед отправкой измененного значения обратно имеется проверка, не был ли установлен соответствующий бит изначально (я где-то читал, что такую проверку делать нужно).
То есть из real mode надо записать, например, по адресу FFFF:FFFF (1114095) если A20 открыта запишется, если нет 20-й бит будет сброшен и попадем в область 65519. Получается у меня изначально открыта, а при закрытии сбрасывается только 20-й бит, а не все что старше. Иначе бы при попытке записи в 1100000000000000000000 запись бы происходила в адрес 0?
Да. А ты уверен, она не происходит? Обработчик деления на ноль вызывается не так часто, поэтому ты мог и не заметить повреждение вектора, находящегося по нулевому адресу.
Я после записи символа B по адресу 1100000000000000000000 (с отключенной A20) вывожу на экран содержимое по адресу 0 и оно отличается от содержимого по адресу 1000000000000000000000