Архитектура 8086 с сегментированной памятью — один из самых часто критикуемых дизайнерских компромиссов в истории. Но автор статьи, проектируя собственный ретро-компьютер Hearthfire, решил разобраться, почему Intel пошла на это. И пришёл к выводу, что идея была не так уж плоха. Всё испортили разработчики.
Ситуация была такая. 8086 мог адресовать 1 МБ памяти — гигантская цифра для эпохи, когда 64 КБ считались роскошью. Для доступа к 20-битному адресу Intel не стала вводить новые большие регистры. Вместо этого они добавили второй набор 16-битных регистров — сегментные. Каждый доступ к памяти комбинировал сегмент и смещение. Внутри CPU сдвигал сегмент на четыре бита влево и складывал со смещением. Два 16-битных значения давали 20-битный адрес. Все ненавидели эту схему.
Но у Intel были веские причины. До 8086 индустрией правил 8080 с его 64 КБ адресного пространства. На нём работала CP/M, код писался на ассемблере. Переписать весь софт под новую архитектуру было немыслимо. Intel предложила элегантное решение: разбить память на 64-килобайтные сегменты. Загружаешь старый код 8080 в один сегмент, настраиваешь сегментные регистры — и он работает без переписывания.
В теории сегментация могла масштабироваться вплоть до 64-битных адресов. Комбинация сегмент+смещение даёт 32 бита — хватило бы на 4 ГБ. Нужно было только наращивать адресные линии.
Но разработчики не захотели работать с изолированными 64-килобайтными блоками. Им нужна была плоская адресная память. Кто-то сообразил, что сегменты всегда отстоят друг от друга на 16 байт. Так родился «нормализованный указатель»: сегментный регистр стал старшими 16 битами адреса, а смещение — младшими четырьмя. Программисты научились обходить сегментацию и работать с памятью как с почти непрерывным пространством.
К моменту выхода 80286 этот паттерн уже устоялся. Intel не могла изменить шаг между сегментами — всё бы сломалось. Пришлось добавлять новый защищённый режим для 24-битной адресации, оставив старый код запертым в real mode. Только 80386 с режимом virtual-8086 позволил окончательно вырваться за пределы 1 МБ.
Автор признаёт: простого решения не было. В идеале нужно было сделать сегменты непрозрачными дескрипторами, без возможности арифметики над ними. Но для хранения их метаданных требовалась память и аппаратное управление — слишком дорого для того времени. В своём проекте Hearthfire он не будет использовать сегментацию 8086, но считает эту историю полезным уроком.