суботу, 27 серпня 2011 р.

Уроки захищеного режиму x86. Весь цикл разом

Закінчивши викладати уроки, вирішив зібрати для зручності всіх їх в один пост.

Історію моєї роботи з ними можна почитати тут, дублювати немає сенсу.

Базою для них послужили уроки захищеного режиму Алексея Фрунзе. Офіційна сторінка тих уроків, http://welcome.to/pmode, на жаль більше не доступна, але див. також сюди: http://members.tripod.com/protected_mode/alexfru/pmtuts.html.

Написано сумбурно, безтолково, однак просто так викинути було шкода. Крім вже згаданої сумбурності та безтолковості, до недоліків належать: багатослівність, місцями спроби охопити все-все-все, ніякий переклад термінів (*). Набір інструментів трішки роздутий, хоча в педагогічних цілях це цілком може бути плюсом. Організація текстів програм мені зараз теж не дуже подобається, але переробляти лінь. Може, як буде попит - в наступній версії.

Можуть бути помилки :-) (Впевнений що вони є)

Крім того це все ж уроки (максимум - лабораторні роботи), тому систематичного викладу роботи захищеного режиму немає. Правда, є багато довідкової інформації. 

Отож, поїхали.

Необхідні інструменти

  • Комп'ютер з 386 або новішим Intel-сумісним процесором. Достатньо лише емулятора, але пробувати час від часу на реальному залізі приємніше.
  • MS-DOS сумісна операційна система для запуску програм уроків. Наприклад FreeDOS.
  • Будь-який текстовий редактор. Під Windows та Linux можна порекомендувати Scite
  • Компілятор OpenWatcom.
  • FlatAssembler
  • The Netwide Assembler (NASM), через те, що хоча FASM  вміє генерувати 16-бітний код, однак він не вміє створювати 16-бітні об'єктні модулі.
  • Додатково користувачам OS Windows можна порекомендувати різноманітні утиліти, що походять з Unix/Linux, з пакету MinGW/MSYS. Поміж них - gcc, GNU make, bash, grep і т.д. Безпосередньо вони не є необхідними, але можуть покращити "якість роботи" (по аналогії з якістю життя)
  • Емулятори, щоб мінімізувати кількість перезавантажень: bochs та qemu. Bochs має зручні засоби відлагодження, але так як емулює процесор і всю апаратуру повністю, дуже повільний. Обидва -- Open Souce. Крім того, можна скористатися і комерційними, типу VirtualBox, VMware, тощо.
  • Під OS Windows -- засоби для роботи з віртуальними дисками. (Під Linux є "вбудований" засіб -- loopback-пристрої). vfd/vdk (Virtual Floppy Drive/ Virtual Disk Driver) чи ImDisk Virtual Disk Driver.
  • Все, що може вам полегшити роботу - файлові менеджери, документація, winamp, пиво, кола і т.д.

Урок номер 0

Ввідний. Опис про що ці уроки, загальні зауваження.

Описано інструменти, які використовуватимуться, типові приклади їх використання, важливі для цих уроків опції (місцями роздуто). Включено qemu, bochs (зокрема детальний опис вбудованих засобів відлагодження), fasm, nasm, Watcom компілятора, лінкера та дизасемблера, VDK/VFK/ImDisk VDD, loopback-пристроїв.
Описано підготовку до роботи та типовий "робочий цикл".

Скачати можна тут: pm_intro.zip. (**)
Додаткові глави:  

Переключаємося в захищений режим (PM), використовуючи CR0 і зразу повертаємося в режим реального адресу. Ніякі системні таблиці не створюються.

При запуску поточний режим процесора перевіряється за допомогою команди SMSW (Store Machine Status Word). Зроблено це для уникнення конфліктів з EMM386 та інших аналогічних менеджерів пам'яті та Windows.

Описано (болдом виділено те, що безпосередньо відноситься до захищеного режиму):
  1. Нюанси компіляції.
  2. Формат регістра CR0.
  3. Особливості таймера BIOS.
  4. Робота з CMOS-пам'яттю.
  5. Заборона чи дозвіл NMI.
  6. Явне вказання регістрів для extern-функцій OpenWatcom (***), асемблерні вставки.
  7. Заплутування (mangling) імен OpenWatcom.
Є як змішана C-asm так і чисто асемблерна реалізації.
  
Архів з файлами уроку: pm_01.zip.


Створюємо GDT. Поміщаємо туди три дескриптори сегментів, які співпадають з відповідними сегментами реального режиму -- сегмент коду, сегмент даних та сегмент стеку. Будуються вони наступним чином: база - CS/DS/SS*10h, ліміт - 0xFFFFh, грануляція - байтова. Крім того, створюємо сегмент що відповідає буферу відеопам'яті -- база 0xB8000h. Всі сегменти - 16-бітні. Створивши таку GDT, переходимо в захищений режим, виводимо на екран повідомлення, "Hello from PMode!", виходимо з нього та завершуємо програму. Так як сервіси BIOS чи DOS нам недоступні, вивід на екран здійснюємо звертаючись безпосередньо до відеопам'яті. 

Описано (болдом виділено те, що безпосередньо відноситься до захищеного режиму):
  1. Формат селектора сегменту. 
  2. Формат дескрипторів, в коді програми - спосіб їх формування.
  3. Типи дескрипторів.
  4. Обчислення лінійної адреси.
  5. Тіньові частини сегментних регістрів.
  6.  Відеопам'ять текстового режиму. Вивід на екран без використання сервісів BIOS чи операційної системи (дуже коротко).
  7. Керування вирівнюванням структур в Open Watcom.
Є як змішана C-asm так і чисто асемблерна реалізації.
Архів з файлами уроку: pm_02.zip.

Та ж GDT що i в другому уроцi. Створюємо IDT (Interrupts Descriptor Table – таблиця дескрипторiв переривань), яка мiстить обробник програмного переривання Int 20h та виключної ситуацiї – дiлення на нуль (Int 0). Перший з них просто виводить повідомлення, другий -- закінчує роботу програми. Продемонстровано їх роботу. Звернiть увагу що обробники є 16-бiтними (типу 286). Зроблено це для простоти.

Описано (болдом виділено те, що безпосередньо відноситься до захищеного режиму):
  • Типи системних дескрипторів.
  • Шлюзи виклику.
  • Шлюзи задач.
  • Шлюзи переривань та IDT.
  • Одним реченням - експорт функції C для використання з асемблерного коду для NASM.
 Є як змішана C-asm так і чисто асемблерна реалізації.
Архів з файлами уроку: pm_03.zip.
Та ж GDT, що і раніше. В IDT -- обробники всіх виключних ситуацій. Реалізовано їх як обгортки, що викликають один і той самий обробник. Обробник виходить з захищеного режиму, виводить тип виключення та його адресу  і закінчує програму. Виділений стек не створюється, тому stack fault (та можливо деякі інші) коректно ним не оброблятимуться. 

Описано:
  • Що таке переривання та виключення (exceptions).
  • Обробники переривань захищеного та реального режиму.
  • Шлюзи пасток, переривань та задач.
  • Спосіб виклик обробника в залежності від причини переривання.
  • Типи виключень -- збої (faults), пастки (traps) та "аварії" (aborts).
  • Дано перелік виключень, що можуть генеруватися процесором.
  • Формат коду помилки для тих виключень, що його генерують. Окремо описано код помилки для Page Fault.
Є як змішана C-asm так і чисто асемблерна реалізації.
Архів з файлами уроку: pm_04.zip. 
Та ж GDT що і й раніше. Майже та сама IDT, що і в 4-му уроці, лише додано два обробника: IRQ0, таймер та IRQ1, клавіатура. Перепрограмовуємо PIC щоб призначити правильні обробники захищеного режиму для IRQ. Програма завершує свою роботу після натиснення ESC. З клавіатурою працює напряму, через контролер.

Описано:
  • Огляд - що таке IRQ (Interrupt ReQuest) і як з ними боротися.
  • Програмування PIC (Programmable Interrupt Controller).
  • Робота з клавіатурою: контролер клавіатури, скан-коди, трішки про роль BIOS.
  • З приводу контролера клавіатури - керування лінією A20 та кілька слів про програмні затримки при вводі-виводі. 
Нових елементів захищеного режиму не вводилося, хіба практично показано як можна обробляти IRQ. Реалізація поки тільки змішана, C-asm. Якщо буде зацікавленість, можна написати і чисто асемблерну.
 
Архів з файлами уроку: pm_05.zip
Додаткові глави: 
Майже те ж, що і в уроці 5. Додано переключення задач. main() переключається на tast(), виконуючи дальній перехід на TSS. Потім task() чекає на клавішу ESC і отримавши її, переключається назад, на main(). Обидві задачі на рівні привілей 0, тому карта дозволу вводу-виводу в TSS не потрібна. Також непотрібними є стеки для міжрівневих переходів --- SS0:ESP0, SS1:ESP1, SS2:ESP2.

Описано:
  • Призначення та формат TSS,
  • Процес апаратного переключення задач,
  • Коротко про нюанси -- ланцюжки задач, шлюзи задач, задачі як обробники переривань, тощо.
Реалізація поки тільки змішана, C-asm. Якщо буде зацікавленість, можна написати і чисто асемблерну.
 
Архів з файлами уроку: pm_06.zip

Продовження теми багатозадачності. Три задачі рівня привілей 0: main(), task1(), task2(). Переключення здійснює планувальник, який викликається з обробника переривань таймера, IRQ0. Багатозадачність із примусовим виштовхуванням (preemptive multitasking) у всій красі.

Нових елементів захищеного режиму не розглядається, на конкретному прикладі в деталях описано процес переключення задачі.
Реалізація поки тільки змішана, C-asm. Якщо буде зацікавленість, можна написати і чисто асемблерну.
 
Архів з файлами уроку: pm_07.zip
Демонстрація роботи трансляції сторінок. У графічному режимі на екран виводиться 16 кольорових смужок, послідовно: 
  • Трансляція сторінок заборонена, послідовність кольорів -- чорний, блакитний, ..., жовтий, білий.
  • Трансляцію ввімкнено, трансляція тотожна, послідовність кольорів та ж -- чорний, блакитний, ..., жовтий, білий.
  • Трансляцію ввімкнено, сторінки перетасовано, послідовність кольорів протилежна -- білий, жовтий, ..., блакитний, чорний.
Використано режим 0x13 VGA, в якому кожному пікселю відповідає рівно один байт. В ньому роздільна здатність 320x200, тому відеопам'ять, яка виводиться на екран, займає 64000 байти, майже 64Кб. Заповнивши різні сторінки байтами, що задають різні кольори ми фактично і безпосередньо візуалізуємо їх  :-)
А візуалізувавши, показуємо, як зміниться зображення, якщо ввімкнути трансляцію, яка  лінійним тотожно ставить у відповідність фізичні (не зміниться) та коли лінійні адреси сторінок відеопам'яті розташовано у зворотному порядку (так як контролер відеоадаптера читає за фізичними адресами, порядок кольорів смужок теж стане зворотнім).

Описано (болдом виділено теми, що безпосередньо стосуються захищеного режиму):

  • Принципи сторінкової організації пам'яті.
  • Її реалізація, директорії та каталоги сторінок. Робота із записами в них. TLB, CR3.
  • Засоби процесора для заміщення сторінок, виключення Page Fault.
  • Розширення механізму сторінкової організації. Регістр CR4, великі сторінки (PSE), доступ до пам'яті за межами 4Гб - 1 (PAE), доступ до пам'яті за межами 4Гб - 2 (PSE-36).  
  • Відеорежим 0x13 VGA-сумісних  адаптерів.
Сторінкова організація в 64-бітному режимі поки не розглядалася. Якщо буде цікаво - пишіть ;-) 

Реалізація поки тільки змішана, C-asm. Якщо буде зацікавленість, можна написати і чисто асемблерну.
 
Архів з файлами уроку: pm_08.zip

Багатозадачність з примусовим витісненням. Основна відмінність від сьомого уроку --- не використовується апаратне переключення задач за допомогою TSS. Збереження контексту здійснюється програмно, за допомогою стеку. Цей спосіб вважається швидшим і більш універсальним, та використовується всіма сучасними промисловими операційними системами.
Нових елементів захищеного режиму не розглядається
Реалізація поки тільки змішана, C-asm. Якщо буде зацікавленість, можна написати і чисто асемблерну.
 
Архів з файлами уроку: pm_09.zip

Цього разу -- адресація до 4Гб оперативної пам'яті з реального режиму, використовуючи недокументовані особливості процесорів. Описано недокументований "нереальний" режим.

Реалізація поки тільки змішана, C-asm. Якщо буде зацікавленість, можна написати і чисто асемблерну.

Архів з файлами уроку: pm_10.zip.


Майже та сама програма, що і в уроці 7. Основна відмінність --- задачі task1() і task2() тепер 32-бітні і працюють на рівні привілей 3, правда за IOPL=3.

Реалізація поки тільки змішана, C-asm. Якщо буде зацікавленість, можна написати і чисто асемблерну.

Архів з файлами уроку: pm_11.zip.


До програми з уроку 11 додано по LDT для кожної задачі рівня привілей 3. Селектори сегментів даних та коду задач тепер знаходяться в їх LDT.

Реалізація поки тільки змішана, C-asm. Якщо буде зацікавленість, можна написати і чисто асемблерну.

Архів з файлами уроку: pm_12.zip.

Всі ці уроки є вступом у використання режиму віртуального 8086 (v8086). На жаль, вони поки без теоретичного опису, лише код із коментарями. Матеріал там відносно простий, однак доволі плутаний. Коли працював над цими уроками, руки не дійшли, а зараз немає ні зацікавленості, ні часу. Однак, якщо буде попит, щось можна придумати :-)
13:
Багатозадачність, як і в попередньому уроці. Одна з двох задач переходить в режим v8086 -- для неї в TSS встановлено відповідний прапорець у EFLAGS.

14:
Додано код, що насправді реалізує роботу в режимі v8086. Підтримуються програмні переривання для задач v86.
15:
Майже повноцінний v86-монітор. IRQ перенаправляються до задачі v86. Завдяки цьому задачі доступні всі функції DOS, прямо як у вікні MS-DOS "віндовса" :-) Про роботу монітора свідчить зірочка, що мерехтітиме в правому верхньому кутку екрану. Запущено command.com (чи що там у вас було в COMSPEC і можна спробувати виконати команди типу dir, чи навіть запустити програми реального режиму.


16:
Крім описаного в попередньому уроці додано підтримку покрокового зневадження (Int 1). Тепер з-під цього монітору працюватимуть і Turbo Debugger і вбудовані зневаджувачі середовищ Turbo Pascal чи Turbo C.

Реалізація поки тільки змішана, C-asm. Якщо буде зацікавленість, можна написати і чисто асемблерну.

Архіви з файлами уроків: pm_13.zip, pm_14.zip, pm_15.zip, pm_16.zip.


Урок номер 17

Базується на уроці 7, використовує апаратну багатозадачність. Показано як користуватися шлюзами виклику. Задача на рівні привілей 3 викликає процедуру з рівня 0. Саме так, за допомогою шлюзів виклику, операційна надає доступ задачам користувацького рівня до своїх сервісів.

Реалізація поки тільки змішана, C-asm. Якщо буде зацікавленість, можна написати і чисто асемблерну.

Архів з файлами уроку: pm_17.zip.

Всі уроки одним файлом
 
Для тих, хто долистав (не кажу - дочитав :) аж сюди - маленький бонус, всі уроки одним файлом.

Увага - bat-файли для компіляції там присутні, але для роботи під чистим DOS їх слід "відтюнити"...

Фініш

Із захищеним режимом (поки? :) все. Закінчилася часточка цієї епопеї тривалістю в 15 років. 

Цікавих тем багато, один тільки 64-бітний режим чого вартий, але ні часу ні особливої зацікавленості поки немає...


Якщо є запитання, виправлення, пропозиції - пишіть! Багато часу цьому приділяти, на жаль, не можу, але якщо з того буде комусь користь - спробуємо щось придумати.

Дякую за увагу
 

Ліцензія

Базою для цих матеріалів служать уроки уроки захищеного режиму Алексея Фрунзе.
Ліцензія на код -- GPL2+.
Ліцензія на тексти -- поки-що GFDL. Можливо, в майбутньому її буде змінено, наприклад на Creative Commons BY-SA.
Довідкова інформація взята з відкритих джерел на просторах Інтернету, зокрема з офіційних мануалів Intel.
Традиційне і очевидне -- жодних гарантій.

Зноски

(*) Хоча, з цим не все так просто. Для деяких з них я знаю "офіційний" (див. http://e2u.org.ua/) переклад, але його звучання мені відверто не подобається... Для інших до нього ще не звик: називати sources "джерельний код", як рекомендує http://linux.org.ua мені подобається, але багаторічна звичка казати "вихідний код" поки переважає.
Я розумію що в цьому виходжу за межі своєї компетентності і здебільшого неправий, але є те що є. 

(**) Незначні зміни, доповнення та виправлення будуть вноситися прямо в файли, про що я старатимуся повідомляти на сторінках уроків (оновлювати цю сторінку буде, напевне, лінь).

Немає коментарів:

Дописати коментар