Пример: Глобальная сеть INTERNET
Я ищу:
На главную  |  Добавить в избранное  

Главная/

Программирование, базы данных. /

Язык макроассемблера IBM PC

←предыдущая следующая→
1 2 3 4 5 6 7 8 9 10 11 12 

слово;  оператор PTR

уточняет, ячейку какого размера мы имеем в виду.)

    И еще одно замечание.  Если  в символьной команде,  оперирующей со словами, указан непосредственный операнд размером в байт,  как, напри­мер, в команде

           MOV AX,80h

то возникает некоторая неоднозначность:  что будет записано  в регистр AX - число 0080h (+128) или 0FF80h (-128)? В подобных ситуациях ассем­блер формирует машинную команду,  где операнд-байт расширен  до слова, причем расширение происходит со знаком,  если операнд  был записан как отрицательное число, и без знака в остальных случаях. Например:

         MOV AX,-128  ; => MOV AX,0FF80h  (A:=-128)


MOV AX,128   ; => MOV AX,0080h   (A:=+128) MOV AX,80h   ; => MOV AX,0080h   (A:=+128)

              1.4. СЕГМЕНТИРОВНИЕ

         1.4.1 Сегменты памяти. Сегментные регистры.

    Первые модели ПК  имели  оперативную  память  объемом  2^16 байтов (64Кб) и потому использовали 16-битовые адреса.  В последующих моделях память была увеличена до 2^20 байтов (1Мб=1000Кб),  для чего уже необ­ходимы 20-битовые адреса. Однако в этих ПК ради сохранения преемствен­ности были сохранены 16-битовые адреса: именно такие адреса хранятся в регистрах  и указываются в командах,  именно такие адреса получаются в результате модмфикации по базовым и индексным регистрам. Как же удает­ся 16-битовыми адресами ссылаться на 1Мб памяти?

Эта проблема решается с помощью сегментирования адресов  (неявного базирования адресов).  В ПК вводится понятие "сегмент памяти". Так на­зывается  любой участок памяти размером до 64Кб и с начальным адресом, кратным 16.  Абсолютный (20-битовый) адрес A любой ячейки памяти можно

представить как сумму 20-битового начального адреса (базы) B сегмента, которому принадлежит ячейка,  и 16-битового смещения D  -  адреса этой ячейки, отсчитанного от начала сегмента: A=B+D. (Неоднозначность выбо­ра сегмента не играет существенной роли,  главное  - чтобы сумма B и D давала нужный адрес.) Адрес B заносится в некоторый регистр S, а в ко­манде, где должен быть указан адрес A,  вместо него  записывается пара из регистра S и смещения D (в MASM такая пара, называемая адресной па­рой или указателем,  записывается как S:D).  Процессор же устроен так, что при выполнении команды он прежде всего по паре S:D вычисляет абсо­лютный адрес A как сумму содержимого регистра S и смещения D  и только затем обращается к памяти по этому адресу A. Вот так, заменяя в коман­дах абсолютные адреса на адресные пары,  и удается адресовать  всю па­мять 16-битовыми адресами (смещениями).

    В качестве регистра S разрешается использовать не любой регистр, а только один из 4 регистров, называемых сегментными: CS, DS, SS и ES. В связи с этим одновременно можно работать с 4 сегментами памяти: начало одного из них  загружается в регистр CS  и  все ссылки на ячейки этого сегмента указываются в виде пар CS:D,  начало другого заносится в DS и все ссылки на его ячейки задаются в виде пар DS:D и т.д. Если одновре­менно надо работать  с большим числом сегментов,  тогда нужно своевре­менно спасать содержимое сегментных регистров  и записывать в них  на­чальные адреса пятого, шестого и т.д. сегментов.

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

    Как и все регистры ПК, сегментные регистры имеют размер слова. По­этому возникает вопрос:  как удается  разместить в них  20-битовые на­чальные адреса сегментов памяти? Ответ такой. Поскольку все эти адреса кратны 16  (см. выше),  то в них младшие 4 бита  (последняя  16-ричная цифра) всегда нулевые, а потому эти биты можно не хранить явно, а лишь подразумевать.  Именно  так и делается:  в сегментном регистре  всегда хранятся только первые 16 битов  (первые четыре 16-ричные  цифры)  на­чального адреса сегмента (эта величина называется номером сегмента или просто сегментом).  При вычислении же абсолютного адреса A по паре S:D процессор  сначала приписывает справа к содержимому регистра S  четыре нулевых бита (другими словами, умножает на 16) и лишь затем прибавляет смещение D, причем суммирование ведется по модулю 2^20:

          Aабс = 16*[S]+D (mod 2^20)

Если, например, в регистре CS хранится величина 1234h,  тогда адресная пара 1234h:507h определяет  абсолютный адрес, равный  16*1234h+507h  = 12340h+507h = 12847h.

         1.4.2 Сегментные регистры по умолчанию

    Согласно  описанной схеме сегментирования адресов, замену абсолют­ных адресов на адресные пары надо производить во всех командах,  имею­щих операнд-адрес.  Однако разработчики ПК придумали способ, позволяю­щий избежать выписывания таких пар в большинстве команд.  Суть  его  в том, что заранее договариваются о том, какой сегментный регистр на ка-

кой сегмент памяти будет указывать,  и  что в командах задается только смещение:  не указанный явно сегментный регистр  автоматически восста­навливается согласно этой договоренности.  И только  при необходимости нарушить эту договоренность  надо полностью  указывать  адресную пару.

Что это за договоренность?

    Считается, что регистр CS всегда указывает на начало области памя­ти, в которой размещены команды программы (эта область называется сег­ментом команд или сегментом кодов),  и  потому  при ссылках  на ячейки этой области регистр CS можно не указывать явно, он подразумевается по умолчанию.  (Отметим  попутно, что абсолютный адрес очередной команды, подлежащей выполнению, всегда задается парой CS:IP:  в счетчике команд IP всегда находится смещение этой команды относительно адреса из реги­стра CS.)  Аналогично предполагается, что регистр DS указывает на сег­мент данных (область памяти с константами, переменными и другими вели­чинами программы), и потому во всех ссылках на этот сегмент регистр DS можно явно не указывать, т.к. он подразумевается по умолчанию. Регистр SS, считается, указывает на стек  -  область памяти,  доступ к которой осуществляется  по принципу  "последним записан - первым считан"  (см. 1.7), и потому все ссылки на стек, в которых явно не указан сегментный регистр, по умолчанию сегментируются по регистру SS. Регистр ES счита­ется свободным, он не привязан ни к какому сегменту памяти и его можно использовать по своему усмотрению;  чаще всего он применяется для дос­тупа к данным, которые не поместились или сознательно не были размеще­ны в сегменте данных.

    С учетом такого распределения ролей сегментных регистров  машинные программы обычно строятся так: все команды программы размещаются в од­ном сегменте памяти,  начало которого  заносится  в регистр CS,  а все данные  размещаются в другом сегменте, начало которого заносится в ре­гистр DS;  если нужен стек, то под него отводится третий сегмент памя­ти, начало которого записывается в регистр SS. После этого практически во всех командах можно указывать не полные адресные пары,  а лишь сме­щения,  т.к. сегментные регистры в этих парах  будут восстанавливаться автоматически.

    Здесь, правда, возникает такой вопрос: как по смещению определить, на какой сегмент памяти оно указывает? Точный ответ приведен ниже (см. 1.4.3), а в общих чертах он такой: ссылки на сегмент команд могут быть только в командах перехода, а ссылки практически во всех других коман­дах (кроме строковых и стековых) - это ссылки на сегмент данных.  Нап­ример, в команде пересылки

         MOV AX,X

имя X воспринимается как ссылка на данное, а потому автоматически вос­станавливается до адресной пары DS:X.  В команде

←предыдущая следующая→
1 2 3 4 5 6 7 8 9 10 11 12 


Copyright © 2005—2007 «RefStore.Ru»