Не совсем i8086. Источник: http://ic.onidev.fr/map/AMD_9586A.html
Не совсем i8086. Источник: http://ic.onidev.fr/map/AMD_9586A.html

Думаю, что ни для кого не секрет, что подавляющее большинство современных ПК используют архитектуру, которой скоро исполнится 50 лет. Ее современный вариант заметно отличается от того, что было в 1978 году, но при этом сохраняет практически полную двоичную совместимость (современные ПК без особого труда запускают MS-DOS, проблемы начинаются при работе с периферией). Я попытался собрать наиболее ключевые особенности, этапы эволюции и поколения архитектуры.

Вступление

1978 год. Произошло несколько политических революций, сменилось трое римских пап, открыли первый спутник Плутона, многие еще не родились, а Intel выпустили 16-битного наследника i8080: i8086, который в последствии практически полностью вытеснил другие архитектуры из потребительских ПК и стал серьезным шагом к стандартизации.

Рынок ПК на тот момент и еще в ближайший десяток лет был слабо похож на современный. Было много относительно бюджетных машин на MOS6502 (Apple I, Apple II, разные Commodore) и Z80 (ZX Spectrum), к середине/концу 80х начали появляться машины на заметно более совершенном и 16/32-битном Motorola 68K (тоже очень интересная архитектура), но общее у них было ровно одно: абсолютная несовместимость ни с кем и никак. Нет, появлялись +- совместимые между собой серии по типу Amiga или Macintosh, но они были проприетарными, а в конечном итоге загнулись (Amiga перерождалась, но в итоге умерла. Macintosh выжил только благодаря удаче и iMac, в последствии перейдя на x86 на много лет).

Причина: IBM-PC.

Про i8086

Во-первых, крайне краткий и упрощенный экскурс в работу наиболее типового процессора Фон-Неймановской архитектуры.

По факту процессор представляет из себя бешенный калькулятор, который последовательно выполняет различные операции и преобразования над числами, попутно управляя самим собой. Для этого у него есть

Многое поменялось, но суть осталась
Многое поменялось, но суть осталась

1. Шина и память. По сути для процессора это одно и то же. Их можно представить как длинную полоску из нумерованных ячеек, способных хранить число от 0 до 255 (представьте себе швейный сантиметр), что не всегда верно (физически шина и память устроены сложно и разделены на много устройств, но при связи по шине они обычно превращаются именно в одномерную ячеистую полоску). Для чего нужна память понимают, наверное, все.

Вместе с этим там же обычно сидят периферийные устройства, к которым можно обращаться так же, как и к памяти. Пункт диапазонов памяти в диспетчере устройств Windows по сути и отвечает за то, как устройства делят эту шину между собой и памятью.

Шина состоит из шины данных, адреса и управления. Ширина шины данных это одна из ключевых характеристик, которая определяет битность процессора, еще от нее сильно зависит скорость работы с устройствами и памятью. По ней передаются, как ни странно, данные. Шина адреса представляет из себя индекс в полоске ячеек, по которому требуется произвести действие. А шина управления используется, к примеру, для выбора между чтением по адресу и записью. 

x86

2. Регистры. Маленькие именованные кусочки памяти внутри процессора. Самое быстрое и легкодоступное, что у него есть (современная разница в скорости по сравнению с памятью примерно как между взять карандаш из ящика (10 секунд) и поехать за ним в магазин (пол часа-час)). Бывают двух ключевых типов: общего назначения и особого (специального) назначения.

Первые обычно имеют размер машинного слова и используются как хранилище операндов для операций. К примеру 2 регистра могут использоваться как слагаемые, после чего в первый будет помещена сумма (особенность многих архитектур в том, что они не могут явно задействовать больше 2 регистров. Частое исключение - FMA). Ко всему прочему, регистры обычно выступают посредником при чтении/записи памяти (опять таки, зависит от архитектуры, но в некоторых вообще запрещены операции напрямую с памятью без предварительной загрузки всего в регистры, другие разрешают только один аргумент для операций брать из памяти). Таких регистров относительно мало, обычно от 4 до 32.

Название вторых крайне общее, ибо все они имеют абсолютно разные предназначения. Чаще всего встречается регистр флагов, в котором каждый бит отвечает или за состояние процессора, или за результат логической операции (для этого обычно есть инструкция CMP, которая вычитает одно число из другого (отбрасывая результат) и заносит в регистр флагов статистику: первое число было больше, меньше, равно, т.д. Потом этим может воспользоваться инструкция условного перехода). Еще есть стековые регистры и регистры, уникальные для архитектуры, но этот экскурс и так слишком длинный.

Самый важный и присутствующий везде регистр: указатель инструкции. Указывает, в какой ячейке памяти находится выполняемая инструкция. Самостоятельно увеличивается после выполнения каждой инструкции, но может быть явно перезаписан инструкцией условного или безусловного перехода на адрес (if-else в языках высокого уровня).

Если вы не закрыли пост, не уснули и за вами не приехала дурка, то продолжаем.

А теперь конкретно про i8086 и x86

20 бит шина адреса, то есть мегабайт ОЗУ, 16 бит шины данных, Фон-Неймановская архитектура, CISC, аппаратные деление и умножение, 4 16-разрядных регистра общего назначения (AX, BX, CX, DX), 8-битные регистры общего назначения, физически совмещенные с 16-битными (AL, AH, BL, BH, т.д. Делят на 2 части 16-битные регистры), 2 индексных (SI, DI. Для строковых операций), 4 сегментных (сегмент кода CS, сегмент стека SS, сегмент данных DS, дополнительный сегмент ES), 16-битный регистр флагов (FLAGS), указатель инструкции (IP). Защиты памяти (MMU) нет, полноценных механизмов многозадачности тоже.

i8088 отличался тем, что имел 8-битную шину данных и технически его можно было назвать 8-битным процессором. Это его замедляло, но зато с ним можно было построить более дешевую систему на старой 8-битной обвязке.

Сегменты

Пропущенная мною часть описания процессора, так как она присуще именно x86 по причине 20-битной шине адреса. Указатель инструкций 16-битный, все операции с памятью тоже 16-битные. Естественно, что 16-битным адресом покрыть все 20 бит адресного пространства было бы как минимум проблемно, как максимум невозможно. Но надмозговые инженеры Intel выход нашли: теперь у нас есть сегменты, а все операции с памятью локальны по отношению к ним. Это создало жуткий геморрой, особенно в высокоуровневых языках (3 типа указателей: ближние, дальние и огромные), но зато облегчило портирование старого ПО с i8080, всё адресное пространство которого влезает в 1 сегмент.

По факту сегмент представляет из себя смещение для логического адреса по отношению к физическому адресу. Значение сегментного регистра умножается на 16 (сдвигается на 4 бита) и прибавляется к логическому адресу для вычисления физического адреса, который будет выдан на шине адреса. Это приводит к тому, что у одного физического адреса появляется 16 логических "синонимов".

Если вы ничего не поняли, то это нормально. Никто не понимает, а потом приходит прозрение (и ночные кошмары). Я не знаю, как это нормально объяснить. У меня есть график, но я не уверен, будет ли он читаем и понятен 

Блоки это сегменты, по горизонтали физическое адресное пространство (1 мегабайт), внутри блоков логический 16-битный адрес (64 килобайта, которые можно адресовать внутри сегмента). Вертикаль показывает наложение логических адресов на физические (те самые 16 "синонимов"). При этом в i80286 возможно переполнение и получение доступа к памяти за пределом 1 мегабайта
Блоки это сегменты, по горизонтали физическое адресное пространство (1 мегабайт), внутри блоков логический 16-битный адрес (64 килобайта, которые можно адресовать внутри сегмента). Вертикаль показывает наложение логических адресов на физические (те самые 16 "синонимов"). При этом в i80286 возможно переполнение и получение доступа к памяти за пределом 1 мегабайта

CISC и RISC

Это легко. CISC предлагает увеличенный набор инструкций взамен на сложность архитектуры и процессора. Время выполнения и длина инструкций может быть совершенно непредсказуемой, иногда встречаются конструкции из высокоуровневых языков (к примеру строковые операции в x86. Подсчет длины строки (strlen()) можно реализовать де-факто одной инструкцией). Удобно для написания на ассемблере, часто не очень удобно для разработчиков компиляторов. Вместе со сложностью растет энергопотребление. Это x86, i8080 и M68K.

RISC же предлагает упрощенный набор инструкций взамен их максимальной оптимизации. Все инструкции должны умещаться в строго одинаковое количество байт. Вместе с этим часто запрещено брать операнды из памяти и увеличено количество регистров. Часто запрещено обращаться к памяти без выравнивания по словам. Иногда даже нет операций деления и умножения, их приходится реализовывать программно. Типовые представители: ARM, RISC-V. MOS6502 можно в некоторой степени назвать RISC, но у него только 1 регистр и один аргумент он всегда берет из памяти (тогда так можно было делать, память была примерно равной по скорости с процессором).

Есть другие варианты, такие как VLIW или шуточные MISC, URISC и ZISC. В дикой природе не встречаются, только если VLIW у "Эльбруса".

А теперь IBM

Сюда хоть кто-то дочитал?
Сюда хоть кто-то дочитал?

Как гром среди ясного неба начался 1981 год, а IBM представили свой IBM-PC, использовавший i8088. И знаете, получилось хорошо. Проблема была одна: дорого (зачем выкидывать пару зарплату на какой-то электронный гроб?). Но их покупали для бизнеса, покупали просто небедные энтузиасты, причем в больших количествах. Ожидания оправдались в 9 раз.

16-килобайтная версия стоила $1,500 (не забывайте про инфляцию, это около $5000 сейчас). Apple II с 4 килобайтами на момент выхода в 1977 стоил $1,298. Но, конечно, к моменту выхода IBM-PC Apple II успел подешеветь и нарастить память, хотя отставание в производительности было колоссальным. Но простенькие машинки Commodore были многократно дешевле и до, и после.

Amiga вышла сильно позже (1985) и в начале тоже стоила неприятно, но потом подешевела и нашла своих покупателей благодаря отличному звуку и графике. Пока IBM предлагал исключительно пищалку и ядовитый EGA (а то и малиново-голубой CGA) вплоть до 87 года за много тысяч, Amiga уже в 1985 предлагала вот такое (а еще графическую многозадачную ОС), а в 1987 делала это же за $800 в базовой комплектации. Очевидно, что покупал обычный человек себе домой, не искушенный бизнесом и работой в Excel.

А теперь главная ошибка IBM, которая их одновременно и погубила, и сделала IBM-PC стандартом: они не стали закрывать архитектуру за патентами и сделали ее крайне расширяемой. Любой мог прийти и купить за небольшую сумму всю необходимую документацию вплоть до исходников BIOS, после чего начать продавать свои платы расширения или вообще компьютеры целиком, полностью совместимые с другими IBM-PC. Причем делать это стали уже через год и очень активно. Так активно, что IBM обос... профукались и в итоге к 2006 году продали свой компьютерный бизнес от греха подальше.

Но статья у нас о поколениях процессоров, так что мы летим назад в 1982 год...

i80286

x86

Технически существовал i80186 и i80188, но они совершенно неинтересны. Не могу сказать, чтобы и i80286 был сильно интересным.

Первое существенное отличие второго поколения x86: шина адреса теперь 24 бита, то есть 16 мегабайт. А в процессоре появился новый режим: защищенный. При этом режим, в котором работал i8086, стал называться реальным. Все последующие процессоры поддерживают все режимы предыдущих, и при этом всегда запускаются в реальном, даже спустя 50 лет. Помимо этого добавили сотню новых инструкций, в основном для работы с защищенным режимом, и нарастили производительность. 

Суть в том, что в реальном режиме был коммунизм: все жили равно и ни у кого не было привилегий ограничений. Но это было крайне опасно, неудобно и мешало созданию полноценных многозадачных ОС, так как любая программа могла залезть в другую и что-нибудь ей поломать, а то и влезть и сломать ОС. Даже не обязательно специально. И на перспективе ограничение на объем ОЗУ начинало переходить из космического в потенциальную проблему недалекого будущего.

Защищенный режим на то и защищенный, что работает в связке с MMU, который позволяет разграничивать регионы памяти под разные программы и привязывать логические адреса к разным физическим адресам, тем самым позволяя реализовать виртуальную память, файлы подкачки и прочее.

Но были у защищенного режима фатальные проблемы. Ключевая: переключаться из реального в защищенный режим было легко, а вот из защищенного в реальный... ну можно было аппаратно сбросить процессор (попросив нажать пользователя на кнопку Reset). Ни о какой одновременной работе защищенного ПО со старым для реального режима речи идти не могло. Потом придумали подвести хитрую схему для программного сброса и вручную сохранять то, что будет при этом сбросе утеряно, но проблему полностью это не решало как минимум из-за серьезных тормозов и отсутствия должных механизмов для "кастрирования" от вредных привычек того, что хочет работать в реальном режиме.

Ничего хорошего из этого выйти не могло, так как всё старое ПО затачивалось под реальный режим с MS-DOS и не могло работать в ОС, использующих защищенный режим. А ОС без программ никому не нужна.

По поводу технической части мне сказать особо нечего, ибо я не работал с этим процессором и практически ничего не знаю о нем. Знаю, что осталась сегментация, но она работала абсолютно иначе и гораздо адекватнее.

I80386

x86

Прошло 3 года. На дворе 1985 год, Intel учли свои ошибки и разработали новый вариант защищенного режима. Это самый интересный и второй по важности режим, который повсеместно использовался вплоть до конца 2000х и продолжает неявно использоваться до сих пор.

Во-первых, теперь процессор стал полностью 32-битным. Поверх старых 16-битных регистров нарастили новые регистры с префиксом 'E'. То есть теперь есть EAX, EBX, EIP, ESP, EBP, EFLAGS и так далее. Но не сегментные регистры, они остались 16-битными. Шина данных и адреса тоже стали 32-битными (шину адреса любят обрезать под лимиты конкретной платформы, но технически ее возможно было сделать 32-битной без модификаций архитектуры. В последствии разработали расширение PAE, что позволило расширить ее свыше 32 линий и 4 гигабайт).

Во-вторых, теперь появился третий (четвертый) режим: виртуальный 8086.Он совмещал в себе особенности работы реального режима и защищенность защищенного, позволяя достаточно эффективно переключаться между ними, а еще реализовывать одновременную работу множества программ реального режима внутри одной ОС одновременно с защищенными. При этом подобный псевдореальный режим оставался достаточно безопасным, так как многие опасные наглости эмулировались и не допускались напрямую к железу, а память была изолирована.

Продолжение следует

К сожалению, мысль о написании подобного текста у меня возникла слишком поздно, а на часах 4 часа 5 часов утра и я уже физически не в состоянии продолжать писать этот пост. Если это будет интересно, то я напишу продолжение, в котором полноценно расскажу про защищенный режим, костыли реального режима и пропущенный промежуток до появления длинного режима (i80486, Pentium). И так страшно представить, сколько неточностей и откровенно грубых ошибок я тут понаписывал на автомате. Если вы их нашли - просьба указать в комментариях

Обещал не делить посты на куски и такой облом, извините