Чому перша інструкція щодо BIOS розташована на 0xFFFFFFF0 ("верх" RAM)?


51

Я знаю, що BIOS завантажує свою першу інструкцію з 0xFFFFFFF0, але чому саме ця адреса? У мене є маса запитань і сподіваюся, що ти зможеш мені допомогти принаймні в деяких із них.

Мої запитання:

  • Чому перша інструкція щодо BIOS розташована у верхній частині 4 Гб оперативної пам’яті?
  • Що буде, якщо мій комп'ютер має лише 1 ГБ оперативної пам’яті?
  • Що з системами з більш ніж 4 ГБ оперативної пам’яті (наприклад, 8 ГБ, 16 ГБ тощо)?
  • Чому стек ініціалізується з деяким значенням (у цьому випадку значенням, розташованим на 0xFFFFFFF0)?

Я читав про це сьогодні вдень, і досі не розумію.


28
Будь-яке питання на запитання, будь ласка.
Гонки легкості з Монікою

4
Мені подобається, як прийнята відповідь взагалі не згадує сегментовану пам'ять або режими адресації, і єдине місце, до якого навіть торкається лінія A20, - це коментарі.
imallett

AVmel Atmel починають виконання з адреси 0, тоді як Freescale HCS08 починається з 0xFFFE, iirc. Кожна сім'я процесорів має свої особливості.
Нік Т

2
@imallett Мені подобається, як ви вирішили скаржитися на це тут, а не просити плаката оновити свою відповідь з додатковою інформацією. Мені також подобається, як ти вважаєш, що ці знання, які ОП зможе помітити, навіть якщо мета задати питання - отримати знання про речі, які зараз можна повністю зрозуміти.
MonkeyZeus

2
На сьогодні @MonkeyZeus, 9 інших коментаторів вже зробили це, і це досі не змінилося. Мій коментар, хоча і саркастичний, не був марним; це попередження для майбутніх нетизенів, а також для ОП.
imallett

Відповіді:


57

0xFFFFFFF0там, де сумісний процесор x86 починає виконувати інструкції при його включенні. Це жорсткий, незмінний (без додаткового обладнання) аспект ЦП та різні типи процесорів поводяться по-різному.

Чому перша інструкція щодо BIOS знаходиться у верхній частині 4 Гб оперативної пам’яті?

Він розташований у верхній частині 4 Гб адресного простору - і при включенні BIOS або UEFI ROM встановлено відповідь на читання цих адрес.

Моя теорія, чому це:

Практично все в програмуванні краще працює з суміжними адресами. Дизайнер процесора не знає, що розробник системи хотів би зробити з процесором, тому це погана ідея, щоб CPU вимагав, щоб адреса smack посередині місця була потрібна для різних цілей. Краще тримати це «поза дорогою» вгорі або внизу адресного простору. Звичайно, майте на увазі, що це рішення було прийняте, коли 8086 був новим, у якому не було MMU .

У 8086 році вектори переривання існували в пам'яті 0 і вище. Вектори переривань повинні знаходитись за відомими адресами, і їх бажано було використовувати в оперативній пам'яті для гнучкості - проте дизайнеру процесора не вдалося знати, скільки оперативної пам’яті буде в системі. Отже, починаючи з 0 і розробляючи сенс для них (тому що жодна система в 1978 році, коли був винайдений 8086, не мала б 4 Гбайт оперативної пам’яті - тому очікувати, що оперативна пам’ять буде 0xFFFFFFF0, не було б гарною ідеєю), і тоді ROM повинен був би бути на верхній межі.

Звичайно, починаючи щонайменше з 80286, вектори переривання можуть бути переміщені в інше початкове місце, відмінне від 0, але сучасні 64-бітні процесори x86 все ще завантажуються в режимі 8086, тому все ще працює старий спосіб сумісності (як смішно як це звучить у 2015 році, щоб і надалі потрібен ваш процесор x86, щоб мати змогу запускати DOS).

Оскільки вектори переривань починаються від 0 і працюють вгору, ПЗУ доведеться починати зверху і працювати вниз.

Що буде, якщо мій комп'ютер має лише 1 ГБ оперативної пам’яті?

32-бітний процесор має 4 294 967 296 адрес, пронумерованих від 0 (0x00000000) до 4294967295 (0xFFFFFFFF). ПЗУ може жити в одних адресах, а ОЗУ - в інших. З процесором MMU це можна навіть перемикати на ходу. Оперативна пам’ять не повинна жити за всіма адресами.

Маючи лише 1 ГБ оперативної пам’яті, деякі адреси не відповідатимуть нічого під час їх читання або запису. Це може призвести до зчитування недійсних даних при доступі до таких адрес або блокуванні системи.

Що з системами з більш ніж 4 ГБ оперативної пам’яті (наприклад: 8 ГБ, 16 ГБ тощо)?

Зробити це дещо просто: 64-розрядні процесори мають більше адрес (що є однією з речей, яка робить їх 64-бітовими - наприклад, 0x0000000000000000 через 0xFFFFFFFFFFFFFFFFFF), наприклад, додаткова оперативна пам'ять «підходить». Якщо припустити, що процесор знаходиться в тривалому режимі . До цього часу оперативна пам’ять є, просто не адресована.

Чому стек ініціалізується з деяким значенням (у цьому випадку значенням, розташованим на 0xFFFFFFF0)?

Я не можу одразу нічого знайти на тому, що x86 призначає покажчик стека при включенні, але, зрештою, доведеться перепризначити процедуру ініціалізації, як тільки ця програма дізнається, скільки оперативної пам’яті в системі. (@Eric Towers у коментарях нижче повідомляє, що він встановлений на нуль при включенні живлення.)


7
Краще думати про адресний простір як про великий простір, в якому речі можуть бути призначені апаратними засобами. Коли процесор читає / записує пам'ять, він фактично здійснює зв'язок по шині, і апаратне забезпечення може переконатися, що такі речі, як RAM або ROM, відповідають у певних діапазонах адрес. Таким чином, таке обладнання повинно переконатися, що ПЗУ реагує на 0xFFFFFFF0, коли процесор скидається. Немає властивого обов'язку, що ПЗУ з'являється відразу після оперативної пам'яті. Він може з’являтися там, де апаратне забезпечення це також говорить, залежно від можливостей такого обладнання.
LawrenceC

4
Можливо, є "дірки" або непризначені пробіли, які не використовуються ПЗУ, ОЗУ чи чим-небудь - зазвичай доступ до них спричинить блокування системи.
LawrenceC

16
Ця відповідь передбачає, що ЦП може використовувати 32 біти адреси, перебуваючи в 16-бітовому режимі. Але в 16-бітному режимі він може використовувати лише 20 біт адреси. Адреса 0xFFFFFFF0недоступна лише після переключення процесора в 32-бітний режим. Востаннє я уважно придивився до коду BIOS 0xFFFF0.
kasperd

6
@ MichaelKjörling ваш розрахунок неправильний. Зміщений сегмент і зсув не ORE, вони додаються. Таким чином, логічний FFFF: FFF0 - це фізичний (1) 0FFE0 (де ведучий 1 присутній, якщо A20 увімкнено).
Руслан

9
@kasperd Там є хакер - менеджер пам'яті має 12 біт, встановлених на 1, до першого стрибка в довжину. Так, логічно, ви працюєте 0xFFFF0, але насправді це відображається на 0xFFFFFFF0. Я вважаю, що це було зроблено для сумісності з 8086 - як видається, використовуються і він, і більш сучасні процесори 0xFFFF0, але 32-бітні процесори насправді отримують доступ 0xFFFFFFF0(відображений на BIOS ROM).
Луань

26

Він не розташований у верхній частині оперативної пам’яті; він знаходиться в ПЗУ, адреса якого знаходиться у верхній частині адресного простору пам'яті, а також будь-яка пам'ять на картах розширення, як контролери Ethernet. Це там, щоб він не конфліктував з оперативною пам’яттю, принаймні, поки у вас не буде встановлено 4 Гб. Системи, які мають 4 Гб або більше оперативної пам’яті, можуть вирішити дві проблеми. Дешеві материнські плати просто ігнорують частини оперативної пам’яті, які суперечать місцем розташування ПЗУ. Достойні перезавантажують оперативну пам’ять, щоб здатися, що вона має адресу вище позначки в 4 ГБ.

Я не впевнений, що ви запитуєте про стек. Це, звичайно, не ініціалізовано бути в ПЗУ. Коли процесор скидається, він спочатку перебуває у «реальному режимі», де він діє так само, як оригінальний 8086, і використовує 16-бітну сегментовану адресацію, дозволяючи йому отримати доступ лише до 1 МБ пам'яті. Код BIOS розташований вгорі, що перевищує 1 Мб. BIOS підбирає десь в оперативній пам’яті для встановлення стека та завантаження та виконує перший сектор першого завантажувального накопичувача. Операційна система повинна переключитися в 32 або 64-бітний режим, як тільки вона перейде і налаштує власні стеки (по одному на завдання / потік).


1
Дуже дякую за відповідь, але @LawrenceC дав більше деталей щодо його відповіді та допоміг мені, як працює вся справа. Все одно, дякую! Я даю вам висновок: 3
Фернандо Паладіні

13

По-перше, це не має нічого спільного з оперативною пам’яттю. Тут ми говоримо про адресний простір - навіть якщо у вас є лише 16 МБ пам’яті, у вас 32-розрядний процесор все одно має повних 32 біт адресного простору.

Це вже дає відповідь на ваше перше запитання - на той час, коли це було розроблено, ПК у реальному світі не було ніде майже повним 4 Гб пам'яті; вони були більше в діапазоні 1-16 МіБ пам'яті. Адресний простір для всіх намірів і цілей був вільним.

Тепер, чому саме 0xFFFFFFF0 саме? Процесор не знає, скільки в ньому є BIOS. Деякі BIOS можуть зайняти лише кілька кілобайт, а інші можуть зайняти повні мегабайти пам'яті - і я навіть не потрапляю в різні додаткові оперативні пам'яті. Процесор повинен бути з'єднаний з якоюсь адресою, щоб почати роботу - немає жодної необхідності конфігурувати процесор. Але це лише відображення адресного простору - адреса відображається безпосередньо в мікросхемі BIOS ROM (так, це означає, що в цей момент ви не отримаєте доступ до повних 4 ГБ оперативної пам’яті, якщо у вас так багато - але це не щось особливе, багато пристроїв потребують власного діапазону в адресному просторі). У 32-розрядному процесорі ця адреса дає вам повних 16 байт, щоб зробити саму основну ініціалізацію - що достатньо для настройки ваших сегментів і, якщо потрібно, режиму адреси (пам’ятайте,реальна завантажувальна "процедура". На даний момент ви взагалі не використовуєте оперативну пам’ять - це всього лише відображений ПЗУ. Насправді оперативна пам’ять навіть не готова до використання до цього моменту - це одне із завдань BIOS POST! Тепер ви можете задуматися - як 16-бітний реальний режим отримує доступ до адреси 0xFFFFFFF0? Звичайно, є сегменти, тому у вас є 20-бітний адресний простір, але це все ще недостатньо добре. Ну, в цьому є хитрість - 12 високих бітів адреси встановлюються, поки ви не виконаєте свій перший стрибок у довжину, надаючи вам доступ до простору адрес з високою адресою (відхиляючи доступ до чого-небудь нижчого, ніж 0xFFF00000 - поки не виконаєте стрибок у довжину) .

Все це речі, які в основному приховані від програмістів (не кажучи вже про користувачів) на сучасних операційних системах. Зазвичай у вас немає доступу до чогось такого низького рівня - деякі речі вже виходять з ладу (ви не можете перемикати режими процесора мимоволі), деякі керуються виключно ядром ОС.

Тож приємніший вигляд відбувається із кодування старої школи на MS DOS. Іншим типовим прикладом пам'яті пристрою, безпосередньо нанесеного на адресний простір, є прямий доступ до відеопам'яті. Наприклад, якщо ви хотіли швидко писати текст на дисплей, ви писали безпосередньо на адресу B800:0000(плюс зміщення - в текстовому режимі 80x25, це означало, (y * 80 + x) * 2якщо моя пам'ять служить мені правильно - два байти на символ, рядок за рядком). Якщо ви хочете намалювати піксель на піксель, ви використовували графічний режим та адресу старту A000:0000(як правило, 320x200 при 8 бітах на піксель). Зробити щось високоефективне, як правило, означало зануритися в посібники з пристроїв, щоб з'ясувати, як отримати доступ до них безпосередньо.

Це збережеться до наших днів - це просто приховано. У Windows ви можете побачити адреси пам’яті, відображені на пристроях у диспетчері пристроїв - просто відкрийте властивості чогось типу вашої мережевої карти, перейдіть на вкладку Ресурси - усі елементи діапазону пам’яті - це відображення пам’яті пристрою до основного адресного простору. І на 32-розрядному рівні ви побачите, що більшість цих пристроїв відображаються над позначкою 2 Гб (пізніше 3 ГБ) - знову ж таки, щоб мінімізувати конфлікти з користувацькою пам'яттю, хоча це насправді не проблема з віртуальною пам'яттю ( програми не знаходяться ніде поблизу реального, апаратного адресного простору - у них є власний віртуалізований фрагмент пам’яті, який може бути відображений, наприклад, в оперативній пам’яті, ПЗУ, пристроях або файлі сторінки).

Що стосується стека, ну, це повинно допомогти зрозуміти, що за замовчуванням стек росте зверху. Отже, якщо ви зробите це push, новий покажчик стека буде на 0xFFFFFEC- іншими словами, ви не намагаєтеся написати на адресу BIOS init :) Що, звичайно, означає, що підпрограми init для BIOS можуть безпечно використовувати стек, перш ніж перекомпонувати його десь корисніше. У програмах старої школи перед тим, як пейджинг став фактичним за замовчуванням, стек зазвичай починався в кінці оперативної пам’яті, і «переповнення стека» траплялося, коли ви починали перезаписувати пам'ять програми. Захист пам’яті багато цього змінив, але в цілому він максимально підтримує сумісність назад - зверніть увагу, як навіть найсучасніший процесор x86-64 ще може завантажувати MS DOS 5 - або як Windows все ще може запускати багато програм DOS, які не мають уявлення про підкачку.


3
Відмінна відповідь, просто розширити і сказати, що сучасні процесори починають скидати хаки, як маскування лінії A20 , тому підтримка старих крайових випадків згасає.
Основні

2
До останнього абзацу: BIOS не може використовувати стек "вільно": він не може записати в ПЗУ (до якого 0xFFFFFFECбуде відображено). Це означає не тільки ні, pushале, наприклад, callні. Вони повинні зачекати, поки оперативна пам'ять буде готова.
The Vee

7

На додаток до інших точок згаданих, це може бути корисно , щоб зрозуміти , що адреса є . Хоча новіші архітектури ускладнюють справи, історично машина на кожному циклі пам’яті виводила бажану адресу на 20 - 32 дроти (залежно від архітектури, з деякими спеціальними хитрощами, щоб зауважити, чи потрібно їй пара чи чотири байти одночасно); різні частини системи пам'яті вивчали б стан цих проводів і активувались, коли бачили певні комбінації високих та низьких значень.

Якщо машині з 32 дротяними адресами потрібно було використовувати лише 1 Мб оперативної пам’яті та 64 КБ ПЗУ (цілком правдоподібно для деяких вбудованих контролерів), вона може активувати ОЗУ для всіх адрес, де провод верхньої адреси був низьким, і ПЗУ для всіх адрес, де він був високий. Нижній провід 20 адрес буде потім прив’язаний до оперативної пам’яті, щоб вибрати один з 1048 576 байт, а нижній 16 також буде підключений до ПЗУ, щоб вибрати один із 65 536 байт. Решта 11 адресних проводів просто не були би підключені ні до чого.

На такій машині доступ до адрес 0x00100000-0x001FFFFF був би еквівалентний доступу до RAM-адрес 0x00000000-0x000FFFFF. Аналогічно з адресами 0x000200000-0x0002FFFFF або 0x7FF00000-0x7FFFFFFFF. Адреси вище 0x80000000 будуть читати ПЗУ, з 64K-картиною, що повторюється у всьому просторі.

Навіть незважаючи на те, що процесор має адресний простір 4 294 967 296 байтів, немає необхідності в апаратному розпізнаванні багатьох різних адрес. Розміщення вектора скидання біля верхньої частини адресного простору - це дизайн, який буде добре працювати незалежно від того, скільки або наскільки мало оперативної пам’яті та ПЗУ система та уникає необхідності повністю декодувати адресний простір.


Хороший момент - Ви не знайдете жодного 64-розрядного обладнання, яке підтримуватиме щось близьке до адресованого 64-бітного простору пам'яті (або навіть 1х10 ^ -12).
Основний

3

Моя теорія полягає в тому, що ми використовуємо негативну логіку, цифровий (1) взагалі не напружує (О вольт). Нам потрібно лише накласти напругу на останні 4 біти при ініціалізації, щоб лічильник програм (або вказівник інструкції) затримувався на 1111 1111 1111 1111 1111 1111 1111 0000. Нам не доводиться звертатися до верхніх 28 біт, оскільки більшість (старих) процесорів) складали 16 біт, а нижні мітки можна адресувати чіпом однієї адреси в старі часи. Оскільки ми маємо 64 біти з сумісністю до 32 біт і 32 біти до 16 біт, апаратне сукупність було вдосконалено, але метод залишається. Також біози не завжди програмують 64 біти або 32 біти. Моя думка також, оскільки спогади не завжди однакові, біоси повинні бути розташовані на тому ж першому сегменті. Те, як ми бачимо адресований біос, не є реальною адресою весь час. Просто вчив мене ...


2

Після RESET на 8088/8086 сумісний процесор виконує вказівки на 0FFFF0, що на 16 байт нижче ліміту на 1 мегабайт. зазвичай ROM в цьому місці (в реалізаціях ПК) буде BIOS, тому наприкінці BIOS ROM відбувається перехід до початку BIOS ROM.

показано тут: початок вектору та підпис 'дата' за ним, IBM 5150 PC 8KB eprom dump data bios: 19.10.1981

00001FEE  FF                db 0xff
00001FEF  FF                db 0xff
00001FF0  EA5BE000F0        jmp word 0xf000:0xe05b
00001FF5  3130              xor [bx+si],si
00001FF7  2F                das
00001FF8  3139              xor [bx+di],di

зауважте, що адресація становить 8 КБ в 2000 ромів, що розміщує стартову адресу (абсолютний далеко JMP, залежно від іншого місця розташування, в даному випадку в межах 8 КМ рому, хоча і не найнижчої можливої ​​адреси в межах цієї роми) на $ FFFF: $ 0 сегментовані або $ FFFF0 лінійні.

що стосується сумісності: якщо якийсь "майбутній" чи поточний процесор "очікує", що перед адресою буде ще набагато більше F, це не має значення. для сумісності новіших процесорів у старих системах додаткові рядки адреси залишаються не пов'язаними, тому дані на шині даних точно такі ж. до тих пір, поки найменш значущі біти залишаються FFFF0.

(у системі, що має лише 1 Мбайт та оперативної пам’яті, розташованої в кінці цього барана, і нічого іншого, воно із задоволенням «подумає», що воно розмовляє з вищою адресою, але отримає ті самі дані, тому що про ці реалізації ніколи не чули адресні рядки вище A19)

зауважте, що світ - це не просто "ПК" ... ПК ibm був "аварією"; ці процесори ніколи не були спеціально розроблені для "ПК" і не вкладаються у багато іншого, ніж просто ПК (наприклад, супутники, системи зброї тощо). 32 і 64-бітний захищений режим, як правило, не бажаний. (віртуальний режим 8086 набагато цікавіший, як причина, наприклад, вибрати нову (386+) версію). тому для "зворотної сумісності" є набагато більше, ніж просто "буде запущено дос".


1

Материнська плата гарантує, що інструкція у векторі скидання - це перехід до місця пам'яті, відображеного до точки входу BIOS. Цей стрибок неявно очищає приховану базову адресу при включенні живлення. Усі ці місця пам'яті мають потрібний вміст, необхідний процесору завдяки карті пам'яті, що зберігається чіпсетом. Всі вони відображені на флеш-пам’яті, що містить BIOS, оскільки в цей момент модулі оперативної пам’яті мають у них випадкове лайно.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.