@daniil14056

Линейный аддресc? Умножение на 16, как это работает вообще и за чем в модели памяти, 32 бит, с 32 бит регистрами?

К примеру 20 бит адресное пространство, и 16 бит регистры, что бы получить линейный адрес 20 бит из 16 битных регистров, нужно A*16+B. Кто до этого извращения додумался? Там бесконечное число решений 16x+c=y. Можно бесконечное число Х и С подобрать что бы получить У. То есть разные значения сегментного регистра и смещения могут дать один и тот же линейный аддрес. В чем смысл. Это же путаница. Почему наоборот, умножают на 16, а не 4096(сдвиг на 12 бит) что бы как раз получился адрес 4 старших бита сегмент, и 16 битов смещение(и пускай он там дальше в физический преобразуется), и ни каких пересечений.
Или вот еще пример CS:IP определяет адрес следующей инструкции. То есть линейный адрес будет CS*16+IP, теперь подставим в CS 0x0500 а в IP 0xFFFF тогда сумма будет = 14fff, а теперь выполняем следующую команду, и получаем 5000,(ffff+1=0) очевидно что программа совершит не предвиденный переход не пойми куда.
Или что CS могут иметь только 4 старших бита не равными нулю?
  • Вопрос задан
  • 64 просмотра
Пригласить эксперта
Ответы на вопрос 3
@galaxy
Вы побухтеть пришли?
Да, вот так это было устроено, сейчас, когда все это уже потеряло всякую актуальность, странно жаловаться. Вы еще не преставляете себе, на какие извращения шли, например, разработчики 8-битных игровых приставок.

теперь выполняем следующую команду, и получаем 5000,(ffff+1=0) очевидно что программа совершит не предвиденный переход не пойми куда

И? У вас код не поместился в сегмент, чьи это проблемы?
Код большого размера (> 65KB) разбивался по разным сегментам. Для переходов у Intel были разные виды jump'ов (far/near).
Ответ написан
@VitalyChaikin
Какая-то каша в ваших рассуждениях;
Есть адресное пространство скажем 1000 байт, а наш регистр адресации не может хранить такое большое число = 1000;
Тогда для того чтобы получить линейный адрес нам необходимы ДВА регистра; R1 и R2
Таким образом чтобы R1*(максимальное_число_которое_может_храниться_в_регистре + 1) + R2 >= 1000
{максимальное_число_которое_может_храниться_в_регистре = 15} от 0 до 15 может хранить байт поэтому умножение производится на 16
К адресу 1000 мы можем обратиться только ОДНИМ способом: R1 = Целое(1000 / 16) ; R2 = ОстатокОтДеления(1000 / 16)
Ответ написан
@Mercury13
Программист на «си с крестами» и не только
У нас маленькие регистры и много памяти. То есть полный адрес задаётся регистровой парой, а не одним регистром. Можно сделать линейную адресацию, а можно сегментную. Объясню логику за сегментами.
1. У нас линейная адресация, и надо по какой-то причине прибавить единицу к адресу. Если нижний адрес переполнится, надо переносить эту единицу в верхний — то есть делать длинный сумматор, увеличивать регистровый файл, постоянно работать с парами регистров и эту пару никак нельзя заменить одним — машина по сути превращается в костыльную 32-битную.
2. Линейная адресация сильно усложняет загрузчики — им приходится обрабатывать так называемые relocations. Задан базовый адрес, и если загрузка случилась по другому. к определённым точкам в памяти надо прибавить разницу. В сегментной адресации этих relocations куда меньше: они задаются по сегментам, а не по точкам. (А в x64 для избавления от relocations ОЧЕНЬ МНОГО команд используют адресацию «от IP».)
3. Совместимость с Intel 8080. Он тогда широко применялся, и IBM пошла на хитрость: после небольшой переделки проги под 8080 работали и на их ПК. Сейчас COM — странная технология Windows, а раньше COM — это было расширение маленьких исполняемых файлов в один сегмент длиной.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы