Коротка відповідь: Кількість доступних адрес дорівнює меншій кількості таких:
- Розмір пам'яті в байтах
- Найбільше без підпису ціле число, яке можна зберегти в машинному слові процесора
Довга відповідь та пояснення сказаного:
Пам'ять складається з байтів (B). Кожен байт складається з 8 біт (b).
1 B = 8 b
1 ГБ оперативної пам’яті насправді становить 1 ГБ (гібібайт, а не гігабайт). Різниця полягає в:
1 GB = 10^9 B = 1 000 000 000 B
1 GiB = 2^30 B = 1 073 741 824 B
Кожен байт пам'яті має свою адресу, незалежно від того, наскільки велике слово машинного процесора. Напр. Процесор Intel 8086 був 16-розрядним і він адресував пам'ять байтами, як і сучасні 32-розрядні та 64-бітні процесори. У цьому причина першого обмеження - у вас не може бути більше адрес, ніж байтів пам'яті.
Адреса пам'яті - це лише кількість байтів, які процесор повинен пропустити з початку пам'яті, щоб дістатися до тієї, яку шукає.
- Для доступу до першого байту потрібно пропустити 0 байт, тому адреса першого байта - 0.
- Для доступу до другого байту потрібно пропустити 1 байт, тому його адреса - 1.
- (і так далі...)
- Для доступу до останнього байту процесор пропускає 1073741823 байт, тому його адреса - 1073741823.
Тепер ви повинні знати, що насправді означає 32-бітове. Як я вже згадував, це розмір машинного слова.
Машинне слово - це об'єм пам'яті, яку CPU використовує для утримування чисел (в оперативній пам'яті, кеші або внутрішніх регістрах). 32-розрядний процесор використовує 32 біти (4 байти) для утримування чисел. Адреси пам'яті теж є цифрами, тому на 32-бітному процесорі адреса пам'яті складається з 32 біт.
Тепер подумайте про це: якщо у вас є один біт, ви можете зберегти на ньому два значення: 0 або 1. Додайте ще один біт і у вас є чотири значення: 0, 1, 2, 3. На трьох бітах ви можете зберегти вісім значень : 0, 1, 2 ... 6, 7. Це насправді двійкова система, і вона працює так:
Decimal Binary
0 0000
1 0001
2 0010
3 0011
4 0100
5 0101
6 0110
7 0111
8 1000
9 1001
10 1010
11 1011
12 1100
13 1101
14 1110
15 1111
Він працює точно як звичайне додавання, але максимальна цифра дорівнює 1, а не 9. Десяткове число 0 є 0000
, потім ви додаєте 1 і отримуєте 0001
, додайте ще раз і у вас є 0010
. Що відбувається тут, як мати десятковий 09
і додавати один: ви змінюєте 9 на 0 і збільшуєте наступну цифру.
З наведеного вище прикладу видно, що завжди існує максимальне значення, яке ви можете зберігати в числі з постійною кількістю бітів - адже коли всі біти дорівнюють 1, а ви намагаєтеся збільшити значення на 1, всі біти стануть 0, таким чином порушуючи значення число. Це називається цілим переповненням і викликає багато неприємних проблем, як для користувачів, так і для розробників.
11111111 = 255
+ 1
-----------
100000000 = 0 (9 bits here, so 1 is trimmed)
- Для 1 біта найбільше значення - 1,
- 2 біти - 3,
- 3 біта - 7,
- 4 біта - 15
Найбільше можливе число завжди становить 2 ^ N-1, де N - кількість біт. Як я вже говорив раніше, адреса пам'яті - це число, і воно також має максимальне значення. Ось чому розмір машинного слова також є обмеженням для кількості доступних адрес пам'яті - іноді ваш процесор просто не може обробити числа, великі для того, щоб отримати більше пам'яті.
Отже, на 32 біті ви можете зберігати числа від 0 до 2 ^ 32-1, і це 4 294 967 295. Це більше, ніж найбільша адреса в 1 ГБ оперативної пам’яті, тому у вашому конкретному випадку об’єм оперативної пам’яті буде обмежуючим фактором.
Обмеження оперативної пам’яті для 32-розрядного процесора теоретично становить 4 ГБ (2 ^ 32), а для 64-бітного процесора - 16 ЕБ (екзабайти, 1 ЕБ = 2 ^ 30 ГБ). Іншими словами, 64-розрядний процесор міг би звертатися до всього Інтернету ... 200 разів;) (за оцінками WolframAlpha ).
Однак в операційних системах реального життя 32-розрядні процесори можуть розміщувати близько 3 ГБ оперативної пам'яті. Це через внутрішню архітектуру операційної системи - деякі адреси зарезервовані для інших цілей. Детальніше про цей так званий бар'єр об'ємом 3 Гб можна прочитати у Вікіпедії . Ви можете зняти цю межу за допомогою розширення фізичної адреси .
Говорячи про адресацію пам’яті, я маю зазначити кілька речей: віртуальна пам’ять , сегментація та пейджинг .
Віртуальна пам'ять
Як зазначав @Daniel R Hicks в іншій відповіді, ОС використовують віртуальну пам'ять. Це означає, що додатки насправді не працюють на реальних адресах пам'яті, а надаються ОС.
Ця методика дозволяє операційній системі переміщувати деякі дані з оперативної пам’яті на так званий Pagefile (Windows) або Swap (* NIX). HDD на кілька масштабів повільніше, ніж ОЗУ, але це не є серйозною проблемою для рідко доступних даних, і це дозволяє ОС надавати додаткам більше оперативної пам’яті, ніж ви насправді встановили.
Пейджинг
Те, про що ми говорили поки що, називається схемою плоскої адреси.
Пейджинг - це альтернативна схема адресації, яка дозволяє адресувати більше пам’яті, яку ви, як правило, могли використати одним машинним словом у плоскій моделі.
Уявіть собі книгу, наповнену 4-літерними словами. Скажімо, на кожній сторінці є 1024 номери. Щоб вирішити номер, ви повинні знати дві речі:
- Кількість сторінки, на якій друкується це слово.
- Яке слово на цій сторінці саме те, що ви шукаєте.
Тепер саме так обробляють пам'ять сучасні процесори x86. Він розділений на 4 сторінки KiB (по 1024 машинних слова кожна), і на цих сторінках є цифри. (насправді сторінки також можуть бути величиною 4 Мб або 2 міБ з PAE ). Коли ви хочете звернутися до комірки пам'яті, вам потрібен номер сторінки та адреса на цій сторінці. Зауважте, що до кожної комірки пам’яті посилається рівно одна пара чисел, що не стосується сегментації.
Сегментація
Ну, цей досить схожий на пейджінг. Він використовувався в Intel 8086, лише щоб назвати один приклад. Групи адрес тепер називаються сегментами пам'яті, а не сторінками. Різниця в тому, що сегменти можуть перекриватися, і вони сильно перекриваються. Наприклад, на 8086 більшість комірок пам'яті було доступно з 4096 різних сегментів.
Приклад:
Скажімо, у нас є 8 байт пам'яті, всі тримають нулі, за винятком 4-го байта, який дорівнює 255.
Ілюстрація для моделі з плоскою пам'яттю:
_____
| 0 |
| 0 |
| 0 |
| 255 |
| 0 |
| 0 |
| 0 |
| 0 |
-----
Ілюстрація для тимчасової пам'яті з 4-байтними сторінками:
PAGE0
_____
| 0 |
| 0 |
| 0 | PAGE1
| 255 | _____
----- | 0 |
| 0 |
| 0 |
| 0 |
-----
Ілюстрація для сегментованої пам'яті з 4-байтовими сегментами, зміщеними на 1:
SEG 0
_____ SEG 1
| 0 | _____ SEG 2
| 0 | | 0 | _____ SEG 3
| 0 | | 0 | | 0 | _____ SEG 4
| 255 | | 255 | | 255 | | 255 | _____ SEG 5
----- | 0 | | 0 | | 0 | | 0 | _____ SEG 6
----- | 0 | | 0 | | 0 | | 0 | _____ SEG 7
----- | 0 | | 0 | | 0 | | 0 | _____
----- | 0 | | 0 | | 0 | | 0 |
----- ----- ----- -----
Як бачите, 4-й байт можна вирішувати чотирма способами: (адресація від 0)
- Сегмент 0, зміщення 3
- Сегмент 1, зміщення 2
- Сегмент 2, зміщення 1
- Сегмент 3, зміщення 0
Це завжди одна і та ж комірка пам'яті.
У реалізованих реалізаціях сегменти зміщуються більш ніж на 1 байт (для 8086 це було 16 байт).
Що в сегментації погано, це те, що це складно (але я думаю, ви це вже знаєте;) Що добре, що ви можете використовувати деякі розумні методи для створення модульних програм.
Наприклад, ви можете завантажити якийсь модуль у сегмент, потім зробити вигляд, що сегмент менший, ніж він є насправді (достатньо малий, щоб утримувати модуль), а потім вибрати перший сегмент, який не перетинається з цим псевдоменшим, і завантажити наступний модуль , і так далі. В основному, таким чином ви отримуєте сторінки змінного розміру.