Короче, это опять я. Посмотрите пожалуйста на код, отвечающий за инициализацию сегмента стэка и определение регистра ESP. В нём есть ошибка. В коментариях есть предыдущий код. Он хоть и рабочий, но явно с ошибкой. Там было написано: MOV AH, Flags1 TASM подставлял вместо Flags1 значение 5. В результате регистр ESP загружался следующим значением: StackBase + StackLimit - 15 + 50000h Сразу видно, что это неправильно, но ЭТО РАБОТАЛО. Когда я пытаюсь сделать правильный код, который вы модете увидеть в TMB.asm, компьютер перезагружается, когда программа использует стэк. Кто-нибудь что-нибудь знает? _1512437955__tmb.ASM
Убери нафиг дескриптор стека из таблицы. Сделай один для IDT, один для кода на всю память, и один для данных на всю память. В SS загрузи дескриптор данных. ESP по желанию. И не парься. Плюсы: меньше фигни - удобство в отладке. ЗЫ. Там где кончается физическая память - начинается MMIO, аккуратнее.
Читать про expand down сегменты. Читать, курить, вьезжать. И не использовать их в реальной жизни Проблемы, которые они решают, лучше и проще решаются с помощью страниц. Хинт: у тебя у сегмента стека тип 0110, а у сегмента данных - 0010. Вот во втором бите собака-то и порылась.
Не въехал. Тип сегмента стека 0110, т.е. для чтения/записи, растёт вниз. ESP указывает почти на конец сегмента. В чём дело то, я этот код сто раз проверял и сверял с учебниками и т.д.?
Неужли так сложно посмотреть документацию? На тему того, что означает "растёт вниз" в данном контексте? Видимо сложно, придётся объяснять. Дескриптор сегмента с типом 0110 описывает expand down сегмент данных. Размер этого сегмента, в частности, поле segment limit, трактуется не так как обычно. Для простоты, далее под segment_limit понимается (segment_limit * гранулярность). В 16-ти разрядном expand down сегмент (разрядность определяется флагом B/D): Код (Text): base_address + segment_limit - начало base_address + 0xffff - конец В 32-х разрядном expant down сегменте: Код (Text): base_address + segment_limit - начало base_address + 0xffffffff - конец При обращении по смещению меньшему segment_limit, выбрасывается исключение. Идея разработчиков была в том, что ты это исключение можешь обработать и уменьшить segment_limit, сдвинув нижнюю границу сегмента ещё немного вниз. Чтобы сразу не выделять под стек кучу памяти, а делать это потом, когда понадобится. Отличие от нормальных сегментов вызвано тем, что стек растёт вниз, т.е. нужно перемещать именно нижнюю границу. Ты ставишь себе ESP меньше чем segment_limit и при первом же обращении к стеку получаешь исключение. Почему же не вызывается твой обработчик исключения? А потому что для вызова обработчика тоже нужен стек, а стека-то и нету. Это называется Double Fault (исключение #DF), но в данном случае даже оно не будет вызвано - сразу машина рестартует. А для того чтобы обработать такое исключение, нужно использовать переключение стеков. То есть исключение должно происходить при CPL отличном от CPL обработчика исключения (обычно 3 и 0 соответственно). Если всё это нормльно инициализировать, то при вызове обработчика будет использован другой стек, с которым пока всё впорядке.
Ещё немного подумал... Чтобы получить переключение стеков не обязательно использовать разные CPL, вместо этого можно сделать обработчик исключения отдельной задачей. Вот оказывается зачем такая возможность нужна, как-то раньше не приходило в голову. Надо будет попробовать.
Если с английским нормально, документацию смотри здесь: http://support.intel.com/design/Pentium4/manuals/253669.htm , PM описан в volume 3. Если с английским не очень, то лучше всего там же, просто это будет труднее Только приготовься - там примерно 800 страниц Ещё есть мои поделки http://sergh.pisem.net/protected.html , они на русском, короче и понятнее, но не закончено, ещё писать и писать.
Все это очень хорошо описано у Григорьева -- "Микропроцессор i486. Архитектура и программирование." Правда, в шестой главе ("Прерывания и ообые случаи") есть очень неприятная ошибка + пара мелких опечаток, но в целом книга очень хорошая. Отчасти и есть перевод документации от Intel.