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

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

в реальном режиме регистры составляют всего 16 бит, поэтому вы можете только адресовать до 64k. Чтобы разрешить адресацию большего объема памяти, addressקד рассчитано по сегменту * 16 + сдвиг.

здесь я могу понять первую строчку. Мы имеем 16 бит, поэтому мы можем адресовать до 2^16 = 64К.

а что это за вторая линия? Что представляет собой сегмент? Почему мы умножаем его на 16? почему мы добавляем смещение. Я просто не могу понять, что это смещение? Кто-нибудь может объяснить мне или дать мне ссылку на это, пожалуйста?

6 ответов


под x86 в реальном режиме памяти физического адреса составляет 20 бит и calcolated:

PhysicalAddress = Segment * 16 + Offset

Смотрите также: Управление Памятью В Реальном Режиме


когда Intel строила 8086, был действительный случай для наличия более 64KB в машине, но не было никакого способа использовать 32-битное адресное пространство. Тогда, даже Мб много памяти. (Помните печально известную цитату "640K должно быть достаточно для любого"? Это, по сути, неправильное понимание того факта, что тогда 1MB был долбаным огромный.) Слово "гигабайт" не будет использоваться в течение еще 15-20 лет, и оно не будет относиться к RAM, как еще через 5-10 лет после этого.

поэтому вместо реализации адресного пространства настолько огромного, что оно" никогда " не будет полностью использовано, они реализовали 20-битные адреса. Они все еще использовали 16-битные слова для адресов, потому что, в конце концов, это 16-битный процессор. Верхнее слово было "сегмент", а нижнее - "смещение". Однако две части значительно перекрывались - "сегмент" - это кусок памяти 64KB, который начинается с (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 процессор) заложил память. Он использует аналогичные обозначения для адресации памяти. Он имеет 64k общей памяти и использует 8-битные значения PAGE:OFFSET для доступа к памяти. Каждая страница имеет длину 256 байт (8-битное число), и смещение указывает на одно из значений на этой странице. Страницы располагаются в памяти спина к спине. Так Страница 2 начинается там, где заканчивается Страница 1. Я шел в 386-й, думая о том же стиле. Это не так.

реальный режим использует аналогичный стиль, даже если это другой сегмент формулировки:OFFSET. Сегмент 64k в размер. Однако сами сегменты не выложены спина к спине, как это было с коммодором. Они находились на расстоянии 16 байт друг от друга. Смещение по-прежнему работает одинаково, указывая, сколько байтов от начала страницы\сегмента.

Я надеюсь, что это объяснение поможет любому, кто найдет этот вопрос, оно помогло мне в его написании.


Я вижу, что вопрос и ответы несколько лет, но есть неправильное утверждение, что в реальном режиме существуют только 16-битные регистры.

в реальном режиме регистры не только 16 бит, потому что есть также 8-битные регистры тоже. Каждый из этих 8-битных регистров является частью 16-битного регистра, которые делятся на нижнюю и верхнюю части 16-битного регистра.

и запуск реального режима с 80386+ мы становимся 32-битными регистрами и дополнительно также два новых префикса инструкций, один для переопределения / обратного размера операнда по умолчанию и один для переопределения / обратного размера адреса по умолчанию одной инструкции внутри codesegment.

эти префиксы инструкции можно использовать в комбинации для того чтобы обратить операнд-размер и адрес-размер совместно для одной инструкции. В реальном режиме размер операнда по умолчанию и размер адреса-16 бит. С этими обоими префиксами инструкций мы можем использовать бит 32 пример операнда / регистра для вычисления 32-разрядного значения в одном 32-разрядном регистре или для перемещения 32-разрядного значения в расположение memmory и из него. И мы можем использовать все 32-битные регистры (возможно, в сочетании с базой+индексом*масштаб+смещение) в качестве адресного регистра, но сумма эффективного адреса не должна превышать предел размера сегмента 64 КБ.

(на странице OSDEV-Wiki мы можем найти в таблице префикс переопределения "размер операнда и размер адреса", который " 0x66 префикс операнда " и "префикс адреса 0x67" является N / A(недоступным) для реального режима и виртуального режима 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 не могут использоваться в реальном режиме.

Кортик


минимальный пример

С:

  • смещение = msg
  • сегмент = ds
mov , %ax
mov %ax, %ds
mov %ds:msg, %al
/* %al contains 1 */

mov , %ax
mov %ax, %ds
mov %ds:msg, %al
/* %al contains 2: 1 * 16 bytes forward. */

msg:
.byte 1
.fill 15
.byte 2

Итак, если вы хотите получить доступ к памяти выше 64k:

mov xF000, %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), но нооооо... Разведка должна была быть странной.

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