Каковы сегмент и смещение в реальном режиме адресации памяти?
12187 просмотра
6 ответа
Я читаю об адресации памяти. Я прочитал о смещении сегмента, а затем о смещении дескриптора. Я знаю, как рассчитать точные адреса в реальном режиме. Все это нормально, но я не могу понять, что именно смещение? Везде, где я читаю:
В реальном режиме регистры имеют только 16 бит, поэтому вы можете адресовать только до 64 КБ. Чтобы разрешить адресацию большего объема памяти, адрес קד рассчитывается по сегменту * 16 + смещение.
Здесь я могу понять первую строку. У нас 16 бит, поэтому мы можем адресовать до 2 ^ 16 = 64 КБ.
Но что это за вторая строка? Что представляет сегмент? Почему мы умножаем это на 16? почему мы добавляем смещение. Я просто не могу понять, что это за смещение? Кто-нибудь может объяснить мне или дать мне ссылку на это, пожалуйста?
Автор: narayanpatra Источник Размещён: 12.11.2019 09:24Ответы (6)
13 плюса
В x86 Real-Mode Memory физический адрес имеет длину 20 бит и вычисляется:
PhysicalAddress = Segment * 16 + Offset
Проверьте также: Управление памятью в реальном режиме
Автор: GJ. Размещён: 07.11.2010 08:3517 плюса
Когда 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, если моя математика верна).
1 плюс
Я хочу добавить ответ только потому, что я искал в интернете, пытаясь понять это тоже. Другие ответы опускали ключевую информацию, которую я получил по ссылке, представленной в одном из ответов. Однако я почти полностью пропустил это. Читая связанную страницу, я все еще не понимал, как это работает.
Вероятно, проблема, с которой я столкнулся, заключалась в том, чтобы понять, как Commodore 64 (процессор 6502) распределяет память. Он использует аналогичные обозначения для адресации памяти. Он имеет 64 КБ общей памяти и использует 8-битные значения PAGE: OFFSET для доступа к памяти. Каждая страница имеет длину 256 байт (8-разрядное число), и смещение указывает на одно из значений на этой странице. Страницы расположены в памяти один за другим. Итак, страница 2 начинается там, где заканчивается страница 1. Я собирался в 386, думая в том же стиле. Это не так.
В реальном режиме используется похожий стиль, даже если он имеет другую формулировку SEGMENT: OFFSET. Сегмент размером 64 КБ. Однако сами сегменты не располагаются вплотную, как Коммодор. Они разнесены на 16 байт друг от друга. Смещение по-прежнему работает так же, указывая, сколько байтов с начала страницы \ сегмента.
Я надеюсь, что это объяснение поможет любому, кто найдет этот вопрос, оно помогло мне написать его.
Автор: Thraka Размещён: 17.12.2012 06:561 плюс
Я вижу, что вопросу и ответам уже несколько лет, но есть неверное утверждение, что в реальном режиме существуют только 16-битные регистры.
В реальном режиме регистры не только 16-битные, потому что есть также 8-битные регистры. Каждый из этих 8-битных регистров является частью 16-битного регистра, который разделен на нижнюю и верхнюю части 16-битного регистра.
И начиная реальный режим с 80386+, мы становимся 32-битными регистрами, а также добавляем также два новых префикса инструкций, один для переопределения / реверсирования размера операнда по умолчанию и один для переопределения / реверсирования размера адреса по умолчанию одной инструкции внутри сегмент кода.
Эти префиксы команд могут использоваться в комбинации для обратного изменения размера операнда и размера адреса для одной инструкции. В реальном режиме размер операнда и размер адреса по умолчанию составляет 16 бит. С этими обоими префиксами команд мы можем использовать пример 32-битного операнда / регистра для вычисления 32-битного значения в одном 32-битном регистре или для перемещения 32-битного значения в и из ячейки памяти. И мы можем использовать все 32-битные регистры (возможно, в сочетании с базой + индекс * масштаб + смещение) в качестве адреса-регистра, но сумма эффективного адреса не должна превышать предел размера сегмента 64 КБ ,
(На странице OSDEV-Wiki мы можем найти в таблице «Префикс размера операнда и размера адреса», что «Префикс операнда 0x66» и «Префикс адреса 0x67» равен N / A (недоступно) для реальный режим и виртуальный режим 8086. http://wiki.osdev.org/X86-64_Instruction_Encoding
Но это в корне неверно, поскольку в руководстве Intel мы можем найти следующее утверждение: «Эти префиксы можно использовать в режиме реального адреса как а также в защищенном режиме и режиме виртуального 8086 ».)
Начиная с Pentium MMX, мы становимся восемью 64-битными MMX-регистрами.
Начиная с Pentium 3, мы становимся восемью 128-битными XMM-регистрами.
..
Если я не ошибаюсь, то 256-битный регистр YMM и 512-битный регистр ZMM и 64-битный регистр общего назначения x64 не могут использоваться в реальном режиме.
кортик
Автор: Dirk Wolfgang Glomp Размещён: 06.02.2014 12:561 плюс
Минимальный пример
С участием:
- смещение =
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
Так что если вы хотите получить доступ к памяти выше 64 КБ:
mov $0xF000, %ax
mov %ax, %ds
Обратите внимание, что это позволяет использовать адреса шириной более 20 бит, если вы используете что-то вроде:
0x10 * 0xFFFF + 0xFFFF == 0x10FFEF
На более ранних процессорах, которые имели только 20 адресных проводников, он был просто урезан, но позже все усложнилось с линией A20 (21-й адресный провод): https://en.wikipedia.org/wiki/A20_line
На репозитории GitHub с необходимым шаблоном для его запуска.
Автор: Ciro Santilli 新疆改造中心法轮功六四事件 Размещён: 07.11.2015 09:07-1 плюса
16-битный регистр может адресовать только до 0xFFFF (65 536 байт, 64 КБ). Когда этого было недостаточно, Intel добавила сегментные регистры.
Любой логический проект просто объединял бы два 16-разрядных регистра для создания 32-разрядного адресного пространства (например 0xFFFF : 0xFFFF = 0xFFFFFFFF
), но неаааа ... Intel пришлось заполучить все это странно.
Исторически передняя шина (FSB) имела только 20 адресных линий и, следовательно, могла передавать только 20-битные адреса. Чтобы «исправить» это, Intel разработала схему, в которой сегментные регистры расширяют ваш адрес только на 4 бита (16 бит + 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 наняла немых инженеров, и мы должны жить с этим.
Автор: James M. Lay Размещён: 22.03.2017 08:11Вопросы из категории :
- memory Setting Objects to Null/Nothing after use in .NET
- memory Предотвращение утечек памяти с прикрепленным поведением
- memory CLR Profiler - Присоединение к существующему процессу
- memory Как определить размер моего массива в C?
- assembly В чем смысл «не временных» обращений к памяти в x86
- assembly How do you get assembler output from C/C++ source in gcc?
- assembly Какой хороший C-декомпилятор?
- assembly Зарегистрируйте правила выделения в коде, сгенерированном основными компиляторами C / C ++
- operating-system Как вы держите машину без сна?
- operating-system Разница между двоичным семафором и мьютексом
- operating-system Налагает ли Java какие-либо дополнительные ограничения на имена файлов, кроме базовой операционной системы?
- operating-system Как я могу проверить использование процессора и памяти в Java?
- x86 Насколько ускорились преобразования 3D-математики в SSE или другие SIMD?
- x86 System.BadImageFormatException: не удалось загрузить файл или сборку (из installutil.exe)
- x86 Какова цель регистра указателя кадра EBP?
- real-mode Каковы сегмент и смещение в реальном режиме адресации памяти?
- real-mode Доступ к памяти в 0xF000FFFE (тип компьютера) в Fasm (MS-DOS)
- real-mode Размер сегмента в реальном режиме x86
- real-mode Близкие таблицы вызовов / переходов не всегда работают в загрузчике