Каковы сегмент и смещение в реальном обращении памяти режима?

StackOverflow https://stackoverflow.com/questions/4119504

Вопрос

Я читаю о адресации памяти. Я читал о смещении сегмента, а затем о смещении дескриптора. Я знаю, как рассчитать точные адреса в реальном режиме. Все это нормально, но я не могу понять, что именно такое смещение? Везде я читал:

В реальном режиме регистры составляют всего 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 наняла некоторых тупых инженеров, и мы должны жить с этим.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top