Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Сегментная модель памяти

76K
14 июня 2013 года
brudor
27 / / 17.04.2013
Привет! Пусть у нас есть .EXE с моделью памяти small. У меня есть несколько вопросов:

1. Когда испольняемый файл грузится в память, у него есть свое виртуальное адресное пространство. Это можно понимать как то, что больше некоторого набора сегментов это приложение под себя забрать не сможет?

2. Обращаться к байтам используя прямую адресацию мы можем как seg:off. Я могу к одному и тому же байту обратится двумя разными способами: например seg_1:offset_1 и seg_2:offset_2

3. После загрузки в память жтого .EXE я могу получить доступ к любыму байту из 64кбайт сегмента данных и могу ли я руками инициализировать новый сегмент под что-нибудь?
326
14 июня 2013 года
sadovoya
757 / / 19.11.2005
Вообще-то смещением принято считать добавку к адресу начала сегмента. Того сегмента, где описано искомое. Непонятно как вы хотите реализовать вариант "seg_1:offset_1 и seg_2:offset_2" , кроме как при seg_1=seg_2 и offset_1=offset_2 ?

Сегментация неплохо описана в Юров "Assembler".
76K
15 июня 2013 года
brudor
27 / / 17.04.2013
Почитал главу про сегментированную модель, вот такая строчка там есть: Каждая программа может состоять из любого числа сегментов, но непосредственный доступ она имеет только к трем основным... Собсственно, а нафига нужны еще сегменты, хотелось бы посмотреть на примере, а то совершенно не понятен смымл этого
326
15 июня 2013 года
sadovoya
757 / / 19.11.2005
Кроме трех основных еще можно один дополнительный сегмент данных привязать к ES. Эти сегменты (кода, данных, стека и дополнительный данных) непосредственно доступны в программе. Вроде как-то еще два можно задействовать. Зачем? По одному сегменту на код, данные и стек необходимо, т.к. у них разное функциональное назначение (хотя можно, например, в коде описать данные, но их тогда надо "перепрыгнуть" иначе процессор начнет "выполнять" данные как код). Дополнительное число сегментов хотелось бы иметь для увеличения программ (сегмент=максимум 64K). Для их получения нужны уже ухищрения. Это сложилось во времена DOS. Сейчас вернулись в основном к единому "сегменту", но размер его 4ГБ. Это "плоская" модель памяти. Появилась благодаря 32-битной адресации и защищенному режиму (гигантское подобие модели tiny в com-программах DOS). Каждая программа в многозадачной ОС "думает" что она владеет всем адресным пространством (реально не более примерно 2ГБ). За отсутствием конфликтов следит ОС. Примерно так. Мог чего-нибудь и наврать, пора мне самому Юрова перечитать:)

Насчет примера, честно говоря, мне слабо. Мне даже 64kB исчерпать не удавалось :)

P.S. Совсем забыл про 64-битные системы упомянуть.
76K
15 июня 2013 года
brudor
27 / / 17.04.2013
sadovoya, большое спасибо Вам за ответы!
У меня осталось еще несколько вопросов. Пусть есть экзешник с моделью small.

1.После запуска спекрва загружается сегмент кода а потом данные или они как-то параллелньо грузятся?

2.
 
Код:
mov ax,@data
mov ds,ax
Что при этом происходит? Если этого не написать, то первые 100h байт сегмента данных будут забиты PSP, а если написать то будут те данные которые мы указали в исходнике. Т.е. мы сдвигаем сегмент данных на 100h и теперь в адресном пространстве программы уже PSP нет, т.е. она не может получить к PSP доступ?
326
15 июня 2013 года
sadovoya
757 / / 19.11.2005
По 1-му вопросу. Код загружается с одного адреса, все данные и стек -- с другого. Вначале exe записысвается PSP (ассемблер сам ее формирует для exe-программ). Насчет, что раньше, что позже грузится не помню.

По 2-му вопросу.

 
Код:
mov ax,@data
mov ds,ax
Происходит загрузка в DS "сегментной составляющей" для дальнейшей адресации конкретных данных.. После этого можно к конкретным данным обращаться кратко, просто по их offset. Без этого PSP ничего не затрет, просто адресация поплывет (точка отсчета неверная будет).
326
16 июня 2013 года
sadovoya
757 / / 19.11.2005
Немного полистав литературу, нашел, что загрузка по-умолчанию идет в порядке описания сегментов в программе. Изменить порядок можно директивами. При загрузке exe в DS сохраняется адрес сегмента PSP. Поэтому вы почти правильно написали последнюю фразу, за исключением "затрет". Действительно, поскольку PSP имеет размер 100h, то добавив в адрес 100h мы и попадем на начало сегмента данных (раз он первым описан у нас). Для адресации без этой поправки мы должны вначале кода перенастроить DS с сегмента PSP на сегмент данных, что мы уже и умеем. Кроме того, как говорилось с этой перенастройкой остается указывать лишь смещение внутри сегмента данных, которое легко берется опреатором offset либо через lea.
PSP мы не теряем, мы к ней можем обратиться, вычтя те-же 100h от адреса первого сегмента, либо (мне кажется удобней) - просто сохранить ее сегментный адрес , например, выпихнув в стек DS в самом начале кода. После этого лучше все-таки DS перенастроить на сегмент данных.

PS. В развитие темы я тут написал один примерчик. Там то, о чем говорили, и еще про то, как можно вывести строку, определенную в коде, а не в данных. Использую для разнообразия альтернативный способ перенастройки адреса. Чтобы русский отображался надо исходник в досовской кодировке писать. Код на Masm, думаю, что в tasm тоже годится.


Код:
.model small

;.stack 128   ;стек (минимум 128 байт надо), но эта программа будет работать и так

.data
     Msg db 'Привет, Мир!!! === $'


.code  

Entry:  
         ;Сегментную составляющую адреса Msg -- в ds:
         mov ax, seg Msg
         mov ds, ax
         ;смещение относительно начала сегмента, где Msg определено (сег. данных):
     mov dx, offset Msg; либо lea dx, Msg

     ;Теперь в паре ds:dx адрес Msg и можно вывести на печать:
         mov ah, 09h        
         int 21h

         ;Аналогично, для данных в коде:
         jmp dat_end ;прыжок через данные, оред. в коде
         msg2 db 'Hi$' ;данные в кодовом сегменте
dat_end:
         mov ax, seg msg2
         mov ds, ax
         mov dx, offset msg2; либо lea dx, msg2
         mov ah, 09h        
         int 21h

         mov ah, 4ch
         int 21h

end Entry
76K
16 июня 2013 года
brudor
27 / / 17.04.2013
Цитата: sadovoya
Вообще-то смещением принято считать добавку к адресу начала сегмента. Того сегмента, где описано искомое. Непонятно как вы хотите реализовать вариант "seg_1:offset_1 и seg_2:offset_2" , кроме как при seg_1=seg_2 и offset_1=offset_2 ?


Юров пишет, что реальный режим допускает перекрывание сегментов, разве это не означает, что мы (гипотетически) можем к одному байту обращаться двумя вариантами "seg_1:offset_1 и seg_2:offset_2"?

326
16 июня 2013 года
sadovoya
757 / / 19.11.2005
Да, физическому адресу может соответствовать множество логических. Физический получается из логического xxxx:yyyy путем домножения xxxx на 16 (т.е. приписыванием нуля к hex значению) и прибавлением yyyy. Но, существует определенная путаница из-за оператора offset. Он берет смещение, но относительно того сегмента, где описана адресуемая штуковина. Поэтому адрес через offset оператор надо записывать используя адрес конкретного сегмента, где описана адресуемое, а не произвольным xxxx. А yyyy в этом случае и есть offset.

PS. Чаще всего, говоря о смещении имеется ввиду смещение внутри сегмента, где адресуемое находится. Но может и вольно где-то трактоваться. Надо в контексте смотреть, обычно можно понять о чем речь.
76K
16 июня 2013 года
brudor
27 / / 17.04.2013
А кем назначается физический адрес? Допустим мы инициализируем байт, он сперва получит физический адрес или логический, где эти адреса находятся (они же должны где-то находится чтобы получать доступ к байтам по его адресу)?
349
16 июня 2013 года
Phantom-84
656 / / 27.10.2005
Привет,

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

1. Не нужно объединять воедино виртуальную память и сегментацию памяти в реальном режиме. Это совершенно разные вещи. Вы вообще уверены, что вам нужно знать, как писать программы под DOS? Может, лучше сразу будете учиться программированию под современные ОС, например, Win32/64? Именно в них используется виртуальная память. А модель памяти называется flat.

2. Можно, но альтернативный адрес нужно формировать вручную, т.к. компиляторы не предполагают наличие пересекающихся сегментов в исполняемом образе - сегменты (группы сегментов) в образе размещаются последовательно с выравниванием на 16 байт.

3. Можно определить сегменты (их нужно разместить в конце образа), данные которых не будут сохраняться в исполняемом файле, но память под них будет автоматически резервироваться при загрузке. Это называется heap. Также резервируется пространство и под стек. Это возможно благодаря спец. полю MINMEMSIZE исполняемого файла. Картина примерно такая:
1) образ, загруженный из файла;
2) резерв памяти, который должен обязательно присутствовать;
3) резерв памяти, которого может и не быть. Данное резервирование возможно благодаря полю MAXMEMSIZE исполняемого файла (обычно устанавливается спец. значение, которое говорит DOS зарезервировать всю память до конца непрерывного блока, выделенного программе - часто это вообще вся доступная базовая память выше базового адреса загрузки). Если установить значение MAXMEMSIZE, равным MINMEMSIZE, то вся не нужная программе изначально память может быть оставлена системе - с этой памятью можно работать при помощи системных функций распределения памяти.

sadovoya, PSP формирует не ассемблер, и не компоновщик, а операционная система. В исполняемом файле нет информации о PSP.
326
16 июня 2013 года
sadovoya
757 / / 19.11.2005
Если по-простому, то реальные адреса - физические. Грубо говоря - номера ячеек памяти. Пересчет логических в физические происходит автоматически. Физический адрес при запуске программы назначается ОС для каждого сегмента программы. От запуска к запуску адреса могут меняться. Инициализировав байт мы можем знать только его положение относительно начала сегмента. А сам адрес сегмента нам надо получать уже в процессе выполнения программы.
Вспомните assume, привязку сегментов к сегментным регистрам. Оператор seg и т.д.
349
16 июня 2013 года
Phantom-84
656 / / 27.10.2005
Цитата: brudor
А кем назначается физический адрес? Допустим мы инициализируем байт, он сперва получит физический адрес или логический, где эти адреса находятся (они же должны где-то находится чтобы получать доступ к байтам по его адресу)?

Перед тем как твоя программа получит управление, DOS настроит в ней все сегментные адреса (@code, @data и т.п.) на основе таблицы релокации, которая хранится в исполняемом файле. Т.е. смещения не изменятся, но благодаря подстройке сегментных адресов у тебя получатся правильные физические адреса, соответствующие реальному местоположению программы в памяти.

326
16 июня 2013 года
sadovoya
757 / / 19.11.2005
Phantom-84, спасибо за замечание по PSP.
76K
17 июня 2013 года
brudor
27 / / 17.04.2013
Я Вас не совсем понял.
Цитата: Phantom-84

2. Можно, но альтернативный адрес нужно формировать вручную, т.к. компиляторы не предполагают наличие пересекающихся сегментов в исполняемом образе - сегменты (группы сегментов) в образе размещаются последовательно с выравниванием на 16 байт.


Можете привести пример кода, где происходит формирование алдьтернативного адреса. Интересно, в каком регистре будет находится адрес сегмента и смещение.

326
18 июня 2013 года
sadovoya
757 / / 19.11.2005
brudor, вы когда в предшествовавшей теме ("Почему смещение именно такое?") писали:

 
Код:
mov dx, offset msg+100h
в той программе DS был выставлен на PSP. Т.е. вы к данным обращались через PSP : (offset msg относительно data) + 100h. Чем вам это не альтернативный адрес? Брался "чужой" для данных сегмент и оффсет внутри "своего" сегмента + поправка 100h. Это работало потому, что PSP непосредственно впритык к адресу сегмента данных размещался. А если бы это был сегмент, заранее не известно, где загружаемый? Думаю, тогда о его адресе надо позаботиться программно, оператором seg, например. Далее арифметика с разницами адресов, поправками... Впрочем сам не экспериментировал, может не все так просто.
76K
18 июня 2013 года
brudor
27 / / 17.04.2013
sadovoya, тогда я навеное не правильно понял, что значит альтернативный адрес. Я думал действовать так: У нас есть адрес байта xxxx:yyyy. Ему соответствует физический (по той формуле, что Вы описывали-- xxxx*10_{16}+yyyy). Далее я думал запихать (например, в es) zzzz и найти смещение tttt, такое что zzzz:tttt=xxxx:yyyy.
326
18 июня 2013 года
sadovoya
757 / / 19.11.2005
Правильно поняли, что же смущает? Вот пример, по той формуле:

Код:
;==========================================================
;      Использование альтернативных адресов
;==========================================================
;Кодировка файла DOS Rus (для русского сообщения)
;Компилировать как exe для Dos

.model small

;стек этой программе не нужен

.data
         org 16  ; нужно, что-бы в минус не залезть при вычитании (ясно будет далее)
     Msg db 'Привет, Мир!!!$'


.code  

Entry:  
         ;настраиваем на данные ds:
         mov ax, @data
         mov ds, ax
         ;смещение помещаем в dx:
         mov dx, offset Msg
         ;Функция 09h прерывания 21h
         ;ждет от нас адрес в паре регистров DS и DX.
         ;У нас в DS сейчас адрес сегмента данных (@data)
         ;а в DX - смещение строки в данных.
         ;Т.е. логический адрес @data:offset Msg.

         ;Адрес наш верен, выводим строку:
         mov ah, 09h        
         int 21h

         ;Увеличим DS на 1 (десятич.)
         mov ax, @data+1
         mov ds, ax
         ;это изменило физический адреc на 16 (десятич.)
         ;компенсируем это в смещении:
         mov dx, offset Msg - 16; (здесь от отриц. смещ. нас страхует org 16 (см. выше))
         
         ;теперь наш альтернативный адрес @data+1:offset Msg - 16
         ;(физический будет тот-же)
         ;Проверяем:
         mov ah, 09h        
         int 21h

         mov ah, 4ch
         int 21h

end Entry
Необычное тут org 16. Просто нужно, чтобы не связываться с отрицательными числами в адресах.
349
18 июня 2013 года
Phantom-84
656 / / 27.10.2005
Да, а если действия над seg smth./offset smth. не прокатят, то можно вычислить и программно. Например:
 
Код:
;
  mov ax,seg data
  dec ax
  mov ds,ax

  mov dx,offset message
  add dx,16
260
19 июня 2013 года
Ramon
1.1K / / 16.08.2003
Сегментация, оверлеи: не, не слышали =^.^=
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог