LINUX.ORG.RU

Про сегментную адресацию

 


1

3

Вяло почитываю про сегментную адресацию первых интеловских камней. (Чувствую себя немного Сальвадором Дали, который тыкал палочкой дохлого ежа).

Я не понимаю, зачем инженеры intel забабахали такую замороченную систему? Сегмент FFFF, к нему камень добавляет 0, чтоб сегмент указывал на границу «параграфа», к этому плюсуется FFFF смещение. Получается вместо требуемых 1 048 576 ячеек – 1 114 096. Неадресуемая память. Плюс к этому смещение может перекрыть параграф, а значит адрес может быть описан разными парами сегмент+смещение. Что, потенциально, может привести к ошибкам.

Возникает вопрос – анакуа Зачем? Зачем 16-битное «смещение»? Зачем плюсование? Логичней ведь просто добавлять последний полубайт?

Или я чего-то не понимаю?

★★★

Для скорости. Адрес сегмента менялся редко.

В те времена памяти было 64k, 128k... Массово 512 появилось горадо позже.

greenman ★★★★★
()
Последнее исправление: greenman (всего исправлений: 1)
Ответ на: комментарий от rechnick

В те годы в компиляторах си явно указывалась модель памяти — Tiny, Small, Medium, Compact, Large, Huge.

greenman ★★★★★
()
Последнее исправление: greenman (всего исправлений: 2)
Ответ на: комментарий от greenman

Для скорости

Не только. Ещё короткие прыжки и т.п. меньше памяти занимают. Но главное, что код с 8080/Z80 на 8086 можно портировать sed'ом, что давало процу приличную кодовую базу даже на момент выхода.

redgremlin ★★★★★
()

Логичней ведь просто добавлять последний полубайт?

Может ты имел в виду первый? Но тогда получается та же схема, только начальные адреса сегментов кратны 64К, а не 16 байт.

no-such-file ★★★★★
()

Получается вместо требуемых 1 048 576 ячеек – 1 114 096. Неадресуемая память

Ещё как адресуемая :) Сами 8086/88, правда, достучаться до этого блока не могли по причине 20-битной адресной шины, но с более поздними процессорами в реальном режиме этой областью пользовались (обычно туда загружались резидентные части доса), чтобы разгрузить те самые 640 килобайт, которых хватит всем.

redgremlin ★★★★★
()

Разве адрес это не ((segment&0xf)<<16)+offset?

никакого перекрытия вроде не было. С другой стороны в i286 можно настроить таблицу дескрипторов и с перекрытиями, иначе как бы работали оверлейные программы из паскаля?

anonymous
()

Логичней ведь просто добавлять последний полубайт?

И что ты предлагаешь - прибить гвоздями размер сегмента в 64Кб, и 16 таких сегментов «хватит на всех»?
Перекрывающиеся сегменты дают гибкость - не обязательно использовать сегменты по 64Кб, можно меньше. Ты можешь юзать сегменты произвольного размера от 16 байт до 64Кб, и таких сегментов может быть много много.

bigbit ★★★★★
()

Тогда Интел умел делать только 16-битные регистры. Более длинные сделать сложнее, потому что нужно сделать весь комплект операций над ними, включая умножение, а это непросто.

Deleted
()
Ответ на: комментарий от Deleted

Тогда Интел умел делать только 16-битные регистры.

А интел об этом знал? Работа над 32-х битным iAPX 432 началась за год до 8086.

Более длинные сделать сложнее, потому что нужно сделать весь комплект операций над ними, включая умножение, а это непросто.

Но для 32-х битной адресации и не надо делать полный набор операций. Можно было сделать также, как в 8-и битных процессорах, задавать адрес парой регистров общего назначения. Просто реальность в то время была такова, что синица в руках (более быстрый и компактный код, совместимый на уровне ассемблера с существующими процессорами) была куда весомее, чем журавль в небе (прямая адресация 4Гб памяти).

redgremlin ★★★★★
()
Ответ на: комментарий от no-such-file

Хотелось бы расшифровки этого утверждения «только начальные адреса сегментов кратны 64К, а не 16 байт». Почему? С моей точки зрения ничего не поменяется. Но ясности станет больше.

rechnick ★★★
() автор топика
Ответ на: комментарий от bigbit

Сегмент даёт адрес с точностью ffff0 (1 048 560), т.е. почти все байты, минус 16. Почему именно по 64кб?

rechnick ★★★
() автор топика
Ответ на: комментарий от rechnick

Почему именно по 64кб

Потому что два байта? не?
Это я к тому что посмотри на опкоды команд штеуда.
Старого штеуда 8086 который.

anonymous
()

В википедии пишут что сначала собирались делать не так:

https://en.wikipedia.org/wiki/Intel_8086

According to Morse et al.,.[5] the designers actually contemplated using an 8-bit shift (instead of 4-bit), in order to create a 16 MB physical address space. However, as this would have forced segments to begin on 256-byte boundaries, and 1 MB was considered very large for a microprocessor around 1976, the idea was dismissed. Also, there were not enough pins available on a low cost 40-pin package for the additional four address bus pins

Собирались делать 8-битное смещение, но из-за экономии памяти (сегменты пришлось бы выравнивать по 256-байтной границе) и из-за того что 1М было тогда очень много, отказались. Про пины непонятно, но раз пишут что не хватало, наверное так и было

Deleted
()

Зачем 16-битное «смещение»? Зачем плюсование?

А как ещё 16 битными регистрами с точностью до байта адресовать 20-битное адресное пространство? Без сегментов не обойтись. Значит не обойтись и без раздельных адреса сегмента и адреса внутри сегмента (смещения). Тут уже только детали начинаются, делать или нет сегменты перекрывающимися. Если модель с перекрытием не приводит к лишним накладным расходам, как было на 8086, то простое суммирование даёт более гибкий результат. Например, можно писать перемещаемые в памяти программы без модификации кода, что активно практиковалось для COM-файлов.

KRoN73 ★★★★★
()
Ответ на: комментарий от rechnick

С моей точки зрения ничего не поменяется. Но ясности станет больше.

ЯННП что ты имел в виду вообще. У тебя есть 2 регистра - сегментный и адресный, оба 16 бит. Что куда ты собрался прибавлять? У интела сегментный регистр смещался на 4 бита влево и складывался с адресным. А ты как я понял предлагаешь чтобы 4 старших бита 20-битного адреса бралось из сегментного и к ним добавлялось 16-бит из адресного? Или как?

значит адрес может быть описан разными парами сегмент+смещение. Что, потенциально, может привести к ошибкам

Так это специально так и задумано - позволяет перемещать код без геморроя с патчингом бинарника при загрузке.

no-such-file ★★★★★
()
Ответ на: комментарий от rechnick

Предлагаю: FFFF0+F

Т.е. использовать сегменты длиной 16 байт? А ничего что непрерывный код должен умещаться в 1 сегмент, т.к. ip тоже работает по этим правилам.

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

Блин, всё – кажись понял...

Именно смещение делает сегмент сегментом. Поэтому оно должно быть до 65536. Поэтому FFFF...

Судя по всему Абель ошибся:

Таким образом, FFFF0h позволяет адресовать до 1048560 байт. Если вы сомневаетесь, то декодируйте каждое F как двоичное 1111, учтите нулевые биты и сложите значения для единичных бит.

Я засомневался только что. Написал скрипт для OO, чтоб наглядно посмотреть адресацию с нулём на конце

https://s23.postimg.org/alwbcpyuz/offset.jpg

Закрашенные ячейки – это реальная адресация (те самые 65536, несмотря на ноль и пять разрядов). Адрес ХХХХ0 достигает только до этих закрашенных. Остальное можно достичь смещением. Если сделать смещение F, то адресация будет полной, да. Но сегмент тогда будет тоже равен F. Следовательно размер сегмента зависит от смещения.

Пока так, а завтра ещё подумаю.

rechnick ★★★
() автор топика
Ответ на: комментарий от rechnick

Похоже ты фигню какую-то понял.
Что непонятного в сегментной арифметике

   XXXX  <- значение сегментного регистра (cs|ds|ss|es)
+   XXXX <- значение смещения внутри сегмента (jmp|call|mov|...)
= YXXXXX <- результирующий адрес на шине адреса
где X = 0..F, Y = 0..1
И ещё.
На проце 8086 было только 20бит на адрес, поэтому в результате было только обращение к 1048576 байтам.
На 80286 процессоре было 24бит на адрес, по этому в результате можно обращаться к 1114095 байтам.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.