Как BIOS ROM отображается в адресное пространство на ПК?

Процессор x86 начинает выполнение по физическому адресу 0xFFFFFFF0. Там, в конце адресного пространства, находится BIOS ROM. Первая инструкция, которую CPU выполняет из ПЗУ, - это большой скачок, который вызывает перезагрузку сегмента CS, поэтому следующая инструкция выполняется из физической области 0x000F0000 - 0x000FFFFF.

Что заставляет ПЗУ реагировать на оба региона? Есть ли какая-то специальная логика декодирования адресов на ПК? Я нашел комментарий в исходном коде Bochs, в котором говорится, что последний 128K BIOS ROM сопоставляется с 0xE0000 - 0xFFFFF. Однако я не могу найти больше информации об этом. Очевидно, что это то, что характерно для ПК, поскольку у меня встроенная плата x86, и такого зеркалирования там не происходит. Я могу использовать только прыжок.

Ответ 1

На ПК всегда присутствует какая-то логика декодирования адреса, потому что в физическом адресном пространстве есть несколько "отверстий/окон", через которые доступ к BIOS ROM и устройствам ввода/вывода (например, видеокарта) доступны вместо ОЗУ. Что по дизайну, по соображениям совместимости, старые программы все еще могут работать на более новых компьютерах.

Что касается начального адреса, по которому ЦП начинает выполнение после reset, если вы посмотрите на документацию, вы увидите, что процессоры класса Pentium начнут с этого:
EIP = 0xFFF0
CS.Selector = 0xF000
CS.Base = 0xFFFF0000

Если вы следуете обычной схеме адресации в реальном режиме, физический адрес должен быть CS.Selector * 16 + IP или, при замене значений, 0xFFFF0. Однако ЦП фактически вычисляет адрес с использованием CS.Base + (E) IP (в реальном и 16/32-битном защищенном режиме, но не в виртуальном 8086 или 64-битном защищенном режиме), следовательно, первый адрес, который запрашивает процессор из памяти будет 0xFFFFFFF0. Ваша невозможность использовать большие переходы для кода внутри ПЗУ на этом высоком адресе может быть связана с тем, что при загрузке в CS будет reset CS.Base до 16 * новое значение CS.Selector. Итак, перепрыгивая, скажем, 0xF000: 0xFFF0 передаст управление в 0xFFFF0 вместо 0xFFFFFFF0, и если ПЗУ также не будет отображено на этом низком месте в памяти, а код в нем подходит для работы с CS (.Selector) = 0xF000, он не будет работать.

Кроме того, ни ЦП, ни схема вокруг него не должны поддерживать все 32 (или более) адресные строки, если на ПК ограничено максимум 16 МБ (как и на i80286 и i80386SX) или 4 ГБ (как это было на i80386DX/original i80386 и i80486) или 2 40-52 (на 64-разрядных процессорах класса Pentium), и если это так, если количество больших бит в физическом адресном пространстве игнорируется, выполнение можно сказать эффективно начать с адреса ниже теоретического максимума - 16, например 0x00FFFFF0 (i80286/i80386SX).

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