Каковы сегмент и смещение в реальном обращении памяти режима?
-
29-09-2019 - |
Вопрос
Я читаю о адресации памяти. Я читал о смещении сегмента, а затем о смещении дескриптора. Я знаю, как рассчитать точные адреса в реальном режиме. Все это нормально, но я не могу понять, что именно такое смещение? Везде я читал:
В реальном режиме регистры составляют всего 16 бит, поэтому вы можете обратиться только к 64 тысяч. Чтобы разрешить адресацию большего количества памяти, адрес קד рассчитывается по сегменту * 16 + смещение.
Здесь я могу понять первую строку. У нас есть 16 бит, поэтому мы можем обратиться до 2^16 = 64K.
Но что это за вторая линия? Что представляет сегмент? Почему мы умножаем его на 16? Почему мы добавляем смещение. Я просто не могу понять, что это за смещение? Кто -нибудь может объяснить мне или дать мне ссылку для этого?
Решение
Под x86 в реальной памяти физический адрес имеет длину 20 бит и раскатывается:
PhysicalAddress = Segment * 16 + Offset
Проверьте также: Реальное управление памятью
Другие советы
Когда Intel строила 8086, в машине было более 64 КБ в машине, но он никогда не использовал 32-разрядное адресное пространство. Тогда даже мегабайт был большой памятью. (Помните печально известную цитату "640K, должна быть достаточно для кого -то"? По сути, это неправильное перевозку того факта, что тогда 1 МБ был чертовски огромный.) Слово «гигабайт» не будет использоваться в течение еще 15-20 лет, и после этого оно не будет ссылаться на Рам еще через 5-10 лет.
Таким образом, вместо того, чтобы внедрить адресное пространство, настолько огромное, что «никогда» никогда «никогда» полностью используется, то, что они делали, было внедрением 20-битных адресов. Они все еще использовали 16-битные слова для адресов, потому что в конце концов, это 16-битный процессор. Верхнее слово было «сегментом», а нижнее слово было «смещением». Однако две части перекрылись - «сегмент» - это кусок памяти 64 КБ, который начинается с (segment) * 16
, и «смещение» может указывать в любом месте в этом куске. Чтобы рассчитать фактический адрес, вы умножаете сегментную часть адреса на 16 (или переключите его на 4 бита ... то же самое), а затем добавляете смещение. Когда вы закончите, у вас есть 20-битный адрес.
19 4 0
+--+--+--+--+
| segment |
+--+--+--+--+--+
| offset |
+--+--+--+--+
Например, если сегмент был 0x8000, а смещение было 0x0100, фактический адрес выходит на ((0x8000 << 4) + 0x0100)
== 0x80100
.
8 0 0 0
0 1 0 0
---------------
8 0 1 0 0
Математика редко бывает такой аккуратной, хотя - 0x80100
может быть представлен буквально тысячами различных сегментов: комбинации смещения (4096, если моя математика верна).
Я хочу добавить здесь ответ только потому, что я тоже исчезал в Интернете, пытаясь это понять. Другие ответы оставляли ключевую информацию, которую я получил по ссылке, представленной в одном из ответов. Однако я почти полностью пропустил это. Читая связанную страницу, я все еще не понимал, как это работает.
Проблема, которую у меня, вероятно, была от меня, только действительно понимая, как Commodore 64 (процессор 6502) изложил память. Он использует аналогичные обозначения для решения памяти. Он имеет 64 тыс. Общей памяти и использует 8-битные значения страницы: смещение для доступа к памяти. Каждая страница имеет длину 256 байтов (8-битное число), а смещение указывает на одно из значений на этой странице. Страницы расположены в памяти. Итак, страница 2 начинается там, где заканчивается страница 1. Я собирался в 386, думая тот же стиль. Это не так.
Real Mode использует аналогичный стиль, даже если это отличный сегмент формулировки: Offset. Сегмент составляет 64 тыс. Размер. Тем не менее, сами сегменты не разложены обратно в спинку, как коммодор. Они находятся на расстоянии 16 байтов друг от друга. Offset по -прежнему работает так же, указывая, сколько байтов от начала сегмента Page .
Я надеюсь, что это объяснение поможет любому другому, кто находит этот вопрос, оно помогло мне в написании его.
Я вижу вопрос, и ответы несколько лет, но есть неправильное утверждение, что в реальном режиме существует только 16 -битные регистры.
В реальном режиме регистры не только 16 бит, потому что есть также 8 -битные регистры. Каждый из этих 8 -битных регистра является частью 16 -битного регистра, который разделен на более низкую и более высокую часть 16 -битного регистра.
И начинать реальный режим с 80386+, мы становимся 32-битными регистрами и дополнительными также двумя новыми префиксами инструкции, один для переопределения/отмены размера операции по умолчанию и один, чтобы переопределить/отменить размер адреса по умолчанию в одну инструкцию внутри инструкции внутри инструкции внутри инструкции в код.
Эти префиксы инструкций могут использоваться в комбинации, чтобы отменить размер операнда и размер адреса вместе для одной инструкции. В реальном режиме по умолчанию и размер адреса по умолчанию-16 бит. С этими префиксами инструкций мы можем использовать 32 -битный пример операнда/регистра, чтобы вычислить 32 -битное значение в одном 32 -битном регистре или для перемещения 32 -битного значения в и обратно и обратно. И мы можем использовать все 32-битные регистры (возможно, в сочетании с базовым+индексным масштабным*масштабным смещением) в качестве режима адреса, но сумма эффективного адреса не должна превышать предел размера сегмента 64 КБ. Анкет
(На странице Osdev-Wiki мы можем найти в таблице для префикса «ПРЕДУПРЕЖДЕНИЕ" 0x66 Operand Size и размером с адрес "и префикс" 0x66 операнда "и префикс адреса 0x67 n/a (не Abiable) для Реальный режим и виртуальный режим 8086. http://wiki.osdev.org/x86-64_instruction_encoding
Но это совершенно неправильно, потому что в руководстве Intel мы можем найти это утверждение: «Эти префиксы можно использовать в режиме реального адреса, а также в защищенном режиме и в режиме Virtual-8086».)
Начиная с Pentium MMX, мы становимся восемью 64-битным MMX-регистраторами.
Начиная с Pentium 3, мы становимся восемью 128-битными XMM-регистраторами.
..
Если я не ошибаюсь, то 256-битный YMM-регистр и 512-битный ZMM-регистр и 64-битный реестр общего назначения X64 не могут использоваться в реальном режиме.
Дирк
Минимальный пример
С:
- offset =
msg
- сегмент =
ds
mov $0, %ax
mov %ax, %ds
mov %ds:msg, %al
/* %al contains 1 */
mov $1, %ax
mov %ax, %ds
mov %ds:msg, %al
/* %al contains 2: 1 * 16 bytes forward. */
msg:
.byte 1
.fill 15
.byte 2
Поэтому, если вы хотите получить доступ к памяти выше 64K:
mov $0xF000, %ax
mov %ax, %ds
Обратите внимание, что это позволяет получить адреса шириной более 20 бит, если вы используете что -то вроде:
0x10 * 0xFFFF + 0xFFFF == 0x10FFEF
На более ранних процессорах, у которых было всего 20 проводов адреса, это было просто усечено, но позже все стало сложным с линией A20 (21 -й адресной проволоки): https://en.wikipedia.org/wiki/a20_line
На GitHub Repo с требуемой шаблоном для запуска.
16-битный регистр может обратиться только к 0xffff (65 536 байтов, 64 КБ). Когда этого было недостаточно, Intel добавила регистры сегмента.
Любой логический дизайн просто объединил бы два 16-битных регистра, чтобы создать 32-разрядное адресное пространство (например, 0xFFFF : 0xFFFF = 0xFFFFFFFF
), но nooooo... Intel должна была получить все странные на нас.
Исторически, на автобусе Frontside (FSB) было только 20 адресов, и, следовательно, могла передавать только 20-битные адреса. К "исправить" Это, Intel разработала схему, в которой регистры сегмента расширяют ваш адрес только на 4-битные (16Bits + 4 = 20, в теории).
Чтобы достичь этого, регистр сегментов оставляется от исходного значения на 4-битные, а затем добавляется к адресу в вашем общем регистре (например [es:ax] = ( es << 4 ) + ax
). Примечание: левое смещение 4 бита эквивалентно умножению на 16.
Вот и все. Вот несколько иллюстративных примеров:
;; everything's hexadecimal
[ 0:1 ] = 1
[ F:1 ] = F1
[ F:0 ] = F0
[ F:FF] = 1EF ; [F becomes F0, + FF = 1EF]
[ F000 : FFFF ] = FFFFF (max 20-bit number)
[ FFFF : FFFF ] = 10FFEF (oh shit, 21-bit number!)
Таким образом, вы все равно можете обратиться к более чем 20-битным. Что происходит? Адрес «оборачивается», например, арифметика модуля (как естественное следствие оборудования). Так, 0x10FFEF
становится 0xFFEF
.
И там у тебя это есть! Intel наняла некоторых тупых инженеров, и мы должны жить с этим.