Многозадачность через task gate мало кто использовал, так что с переходом к 64 битам потеря невелика. В TSS осталось то, что существенно: копии указателей стэка для колец 0…2, указатель на битмэп доступа к портам, и новая штука, IST. Это вроде справочника хороших указателей стэка для обработчиков прерываний/исключений, дескриптор в IDT говорит, который использовать. Так что TSS жив и здоров, хотя к многозадачности уже не имеет отношения.
baldr Не указатель, а смещение. Битовая карта должна располагаться в пределах сегмента TSS, смещение по умолчанию устанавливается за пределами сегмента, таким образом все обращения к портам будут генерировать исключение. Смещение можно установить через Ke386IoSetAccessProcess, в винде больше 1й битовой карты установить не получиться (изза размеров сегмента TSS). з.ы. автор, читай доки и не мучай форум =]
TSS Конечно я документации читаю (с переводчиком) но всё же, для того он и форум, чтобы люди помогали друг другу. Да тем более я форум не загаживаю, создал тему и в ней всё спрашиваю. А кто-нибудь создавал свою операционную систему с графической оболочкой, наподобие как Windows?
У меня беда. Вместе с ещё одним парнем изучаем процессор и пытаемся написать свою операционную систему. Вот я начал вчера делать загрузчик. Написал код, всё нормально работало. А когда сегодня добавил туда комментарии (украшения), то у меня клавиши стали работать на оборот: Enter - выход, а Escape - установка. Хотя должно быть наоборот. Не понимаю что я мог изменить. По коду вроде всё правильно. У меня уже рассудок замутнён. У кого свежий взгляд, посмотрите, пожалуйста что не так: Code (Text): ; Имя: Boot ; Описание: Загрузочный сектор ; Автор: Дубровкин Сергей ; Начало: 21.10.2010 - 17:54 ; Завершение: ??.??.???? - ??:?? use16 org 0x7C00 ; ******************************************************************************* ; К О Д ; ******************************************************************************* bootCode16: mov AX,CS mov DS,AX mov ES,AX mov FS,AX mov GS,AX mov AX,bootStack16 mov SS,AX mov AX,bootStackStart16 mov SP,AX call BootSaveScreen call BootInitScreen mov BL,00000000b call BootClearScreen mov SI,bootTextTitle mov BL,00001111b mov DH,2 mov DL,32 call BootDrawText mov SI,bootTextDescription mov BL,00001111b mov DH,3 mov DL,27 call BootDrawText mov SI,bootTextKey1 mov BL,00001111b mov DH,10 mov DL,26 call BootDrawText mov SI,bootTextKey2 mov BL,00001111b mov DH,12 mov DL,28 call BootDrawText mov SI,bootTextAutors mov BL,00001111b mov DH,22 mov DL,20 call BootDrawText mov SI,bootTextYear mov BL,00001111b mov DH,23 mov DL,36 call BootDrawText call BootKeyDown test AL,AL jz BootLabelEnd ; -------------------------------------------------------------------{ ; В Р Е М Е Н Н О ; -------------------------------------------------------------------- mov DH,0x00 mov DL,0x00 call BootSetCursorPos mov BL,00010000b call BootClearScreen mov SI,bootTextOK mov BL,00011010b mov DH,1 mov DL,1 call BootDrawText label1: jmp label1 ; -------------------------------------------------------------------} BootLabelEnd: call BootLoadScreen int 0x18 ; ******************************************************************************* ; П Р О Ц Е Д У Р Ы ; ******************************************************************************* ; ------------------------------------------------------------------------------{ ; Название: BootKeyDown() ; Описание: Нажатие клавиши ; Вход: Нет ; Выход: AL - код ; ------------------------------------------------------------------------------- BootKeyDown: BootKeyDownRepeat: mov AH,0x00 int 0x16 test AH,0x01 jz BootKeyDownEscape test AH,0x1C jz BootKeyDownEnter jmp BootKeyDownRepeat BootKeyDownEscape: mov AL,0x00 jmp BootKeyDownEnd BootKeyDownEnter: mov AL,0x01 BootKeyDownEnd: ret ; ------------------------------------------------------------------------------} ; ------------------------------------------------------------------------------{ ; Название: BootSaveScreen() ; Описание: Сохранение видео-режима ; Вход: Нет ; Выход: Нет ; ------------------------------------------------------------------------------- BootSaveScreen: mov AH,0x0F int 0x10 mov [bootScreenMode],AL mov [bootSymbols],AH mov [bootPageNumber],BH ret ; ------------------------------------------------------------------------------} ; ------------------------------------------------------------------------------{ ; Название: BootLoadScreen() ; Описание: Загрузка видео-режима ; Вход: Нет ; Выход: Нет ; ------------------------------------------------------------------------------- BootLoadScreen: mov AH,0x00 mov AL,[bootScreenMode] int 0x10 mov AL,[bootPageNumber] call BootSetScreenPage ret ; ------------------------------------------------------------------------------} ; ------------------------------------------------------------------------------{ ; Название: BootInitScreen() ; Описание: Инициализация видео-режима ; Вход: Нет ; Выход: Нет ; ------------------------------------------------------------------------------- BootInitScreen: mov AH,0x00 mov AL,0x03 int 0x10 ret ; ------------------------------------------------------------------------------} ; ------------------------------------------------------------------------------{ ; Название: BootClearScreen() ; Описание: Очистка экрана ; Вход: BL - цвет ; Выход: Нет ; ------------------------------------------------------------------------------- BootClearScreen: mov AH,0x09 mov AL,' ' mov BH,0x00 mov CX,2000 int 0x10 ret ; ------------------------------------------------------------------------------} ; ------------------------------------------------------------------------------{ ; Название: BootSetScreenPage() ; Описание: Установка страницы ; Вход: AL - номер страница ; Выход: Нет ; ------------------------------------------------------------------------------- BootSetScreenPage: mov AH,0x05 int 0x10 ret ; ------------------------------------------------------------------------------} ; ------------------------------------------------------------------------------{ ; Название: BootSetCursorPos() ; Описание: Установка положения курсора ; Вход: DH - номер строки ; DL - номер столбца ; Выход: Нет ; ------------------------------------------------------------------------------- BootSetCursorPos: mov AH,0x02 mov BH,0x00 int 0x10 ret ; ------------------------------------------------------------------------------} ; ------------------------------------------------------------------------------{ ; Название: BootDrawText() ; Описание: Вывод текста ; Вход: BL - атрибуты текста ; DH - номер строки ; DL - номер столбца ; Выход: Нет ; ------------------------------------------------------------------------------- BootDrawText: mov CX,1 BootDrawTextLoop: call BootSetCursorPos mov AH,0x09 mov BH,0x00 lodsb test AL,AL jz BootDrawTextExit int 0x10 inc DL jmp BootDrawTextLoop BootDrawTextExit: ret ; ------------------------------------------------------------------------------} ; ******************************************************************************* ; Д А Н Н Ы Е ; ******************************************************************************* bootData16: bootScreenMode db 0x00 bootSymbols db 0x00 bootPageNumber db 0x00 bootTextTitle db "Hello in BOS!",0x00 bootTextDescription db "(Basic Operation System)",0x00 bootTextKey1 db "Press 'Enter' for continue.",0x00 bootTextKey2 db "Press 'Escape' for exit.",0x00 bootTextAutors db "Dubrovkin Sergei & Konstantin Dement'ev",0x00 bootTextYear db "(2010)",0x00 bootTextOK db "You in press 'Enter' key.",0x00 ; ******************************************************************************* ; С Т Е К ; ******************************************************************************* bootStack16: db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 bootStackStart16: db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; ******************************************************************************* ; Д О П О Л Н И Т Е Л Ь Н О ; ******************************************************************************* ; Заполнение до 510 байт rb 510-($-$$) ; Метка загрузочного сектора db 0x55,0xAA ; Дубровкин Сергей © 2010
Если не хочешь использовать шлюзы вызова, то используй syscall/sysret. Это более быстрый механизм и используется во всех современных ОС. А факт наличия 64-битности гарантирует поддержку этого механизма. test al, al = cmp al, 0 в остальных ситуациях test для сравнения не нужен.
А если я перейду в защищённый режим, создам странички и опишу в страничке диапазон от 0x0000B800 до 0x0000B800 + 4 МБ, то я смогу при обращении к этой странички напрямую записывать данные в видеобуфер? И так же в длинном режиме? Правда не совсем понятно как тогда определить какая страничка что адресует, ведь они же сделаны для виртуальной памяти. Ладно с сегментами, их чётко привязываешь к адресу.
Судите как хотите, но я начал разрабатывать свой ассемблер. Первым делом решил рассмотреть команды пересылки данных (MOV). Вот табличка из документации Intel: Собственно из регистра в регистр, из памяти в регистр и из регистра в память - это всё понятно. А вот из immediate в регистр и память - это я не понимаю что вообще такое (а главное только в, а не из). Что это? То что существует по два опкода для одного и того же действия, это я уже давно знал (поменять бит направления и поменять местами регистры). Но вот увидел что написано в таблице: Удивительно, это получается что команду: Code (Text): mov EAX,ECX Можно записать в четырёх записях? А собственно зачем нужно: Ведь это можно реализовать и через: Какое от них преимущество?
> в остальных ситуациях test для сравнения не нужен. м? а проверка соответствующих битов? например битовые флаги очень удобны.
Ребят, тут я задумался... Создавать операционную систему я хочу. Я уже давно пытался и не раз, но всё заканчивалось тем, что я плевал на это дело. А теперь всё, решил - делать буду до конца. Но задумался я не об этом. Я же хочу создавать свой ассемблер, чтобы на нём делать операционную систему. Вот и думаю...напишу я под Windows ассемблер на языке C++, который будет использовать функции Win32 API. Напишу я на нём операционную систему. А дальше то что? Моя операционная система не знает ни исходных кодов на языке C++, ни функций Win32 API - другая операционная система, всё другое. То есть ассемблер мне нужно будет делать с нуля именно для моей операционной системы. Вот и думаю, стоит ли мне сейчас его делать под Windows или нет. Хочется, но вот двойную работу ведь выполнять придётся, не получится же просто взять и портировать. Что Вы думаете по этому поводу?
Многие хотели. Обычно желание заканчивается при попытке реализации(разумеется если не копипаст линуса). В особо тяжёлых случаях желание исчезает на стопяцот к строке, после чего кодера осеняет что затея гиблая и лучше юзать уже созданные системы, тем более что создать подобную NT ось с нуля невозможно. А с вопросами про пэйджинг и прочее как можно вообще и думать про написание оси, это же элементарные принципы.
Я имел ввиду test как альтернативу cmp. То что у него есть и "штатные" функции я не спорю - сам им для этих целей пользуюсь. Ты можешь пользоваться не WinAPI, а libc. Для ассемблера его хватит. Только вот тебе ещё придётся писать и компилятор С++ для своей ОС. Или писать Ассемблер на самом себе. Второй вариант мне кажется менее трудоёмким (если синтаксис будет совместим с одним из существующих, то для первой компиляции будет использоваться он, а потом уже твой ассемблер). А вообще затея бессмысленна. Ты реши уж что хочешь написать - свою ОС, свой Ассемблер, свой компилятор C++. Каждая задача по отдельности реальна (хотя первая займёт очень много времени). Но реализовать всё вместе нет. Пока ты напишиешь нормальный компилятор C++ желание писать ОС уже не будет. Аналогично с асмом. Лучше посвяти всё время написанию ОС. Хоть её ты напишешь (хотя конкурента Windows или Linux - нет. тут нужен не один человек и не один год работы). Уж лучше запускай fasm в 32-битном сегменте. Ничего плохого в этом нет. Особых сложностей с реализацией - тоже. Ага. Надо соблюдать принцип "от простого к сложному". Сначала как следует изучи реальный режим. Потом PM. Потом PM со страничной адресацией. И только тогда long mode. И если желание останется - пиши свою ОС. Но не свой Ассемблер. )))
s3dworld Более-менее знать английский для занятий системным программированием абсолютно необходимо, без этого там делать ровным счётом нечего. Так что учите.
s3dworld, Готов подписаться под каждым словом предыдущего оратора. P.S. Чтобы добавить конструктива — могу предложить помощь в переводе/понимании замороченных мест в Intel SDM/AMD APM.
baldr Спасибо, я Вас в ICQ добавил. Ребят, от слов перешёл к дело. Начал писать код перехода. Хочу спросить Ваши советы по поводу написания кода: что не так, как лучше бы и прочее. И правильно ли я заполнил таблицу дескрипторов (нулевой, для кода на уровне 0, для данных на уровне 0, для кода на уровне 3 и для данных на уровне 3). Для всех них (кроме нулевого) база в 0 и максимальный предел (4 ГБ). Видимо придётся туда ещё добавлять системные дескрипторы (ведь без прерываний никак), так как шлюзы вызова, ловушки и задачи - это ведь всё тоже лежит в GDT (вроде бы). А вот сам код (пока только начал): Code (Text): ; Имя: translation_pmode ; Описание: Перевод процессора в защищённый режим ; Автор: Дубровкин Сергей ; Начало: 23.10.2010 - 11:48 ; Завершение: ??.??.???? - ??:?? ; ******************************************************************************* use16 ; ******************************************************************************* ; К О Д ; ******************************************************************************* translation_pmode__Code16: hlt translation_pmode__Code32: hlt ; ******************************************************************************* ; Д А Н Н Ы Е ; ******************************************************************************* translation_pmode__Data16: translation_pmode__gdt: translation_pmode__descriptor0: db 00000000b ; Base Address(8) db 00000000b ; G(1), D(1), NULL(1), AVL(1), Segment Limit(4) db 00000000b ; P(1), DPL(2), S(1), Type(4) db 00000000b ; Base Address(8) dw 0000000000000000b ; Base Address(16) dw 0000000000000000b ; Segment Limit(16) translation_pmode__descriptor1: db 00000000b ; Base Address(8) db 11001111b ; G(1), D(1), NULL(1), AVL(1), Segment Limit(4) db 10011000b ; P(1), DPL(2), S(1), Type(4) db 00000000b ; Base Address(8) dw 0000000000000000b ; Base Address(16) dw 1111111111111111b ; Segment Limit(16) translation_pmode__descriptor2: db 00000000b ; Base Address(8) db 11001111b ; G(1), D(1), NULL(1), AVL(1), Segment Limit(4) db 10010010b ; P(1), DPL(2), S(1), Type(4) db 00000000b ; Base Address(8) dw 0000000000000000b ; Base Address(16) dw 1111111111111111b ; Segment Limit(16) translation_pmode__descriptor3: db 00000000b ; Base Address(8) db 11001111b ; G(1), D(1), NULL(1), AVL(1), Segment Limit(4) db 11111000b ; P(1), DPL(2), S(1), Type(4) db 00000000b ; Base Address(8) dw 0000000000000000b ; Base Address(16) dw 1111111111111111b ; Segment Limit(16) translation_pmode__descriptor4: db 00000000b ; Base Address(8) db 11001111b ; G(1), D(1), NULL(1), AVL(1), Segment Limit(4) db 11110010b ; P(1), DPL(2), S(1), Type(4) db 00000000b ; Base Address(8) dw 0000000000000000b ; Base Address(16) dw 1111111111111111b ; Segment Limit(16) translation_pmode__Data32: ; ******************************************************************************* ; С Т Е К ; ******************************************************************************* translation_pmode__Stack16: db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 translation_pmode__StackStart16: db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 translation_pmode__Stack32: db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 translation_pmode__StackStart32: db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 rb (1024*1024*1)-1-($-$$) db 0x00 Всё верно? Кстати, а как загрузить в регистр GDTR значение где у меня таблица? Там ведь нужно указывать базовый адрес и предел (вроде бы). А как именно указывать, чтобы это попало в GDTR (SGDT/LGDT)?