Упрощенные Директивы Сегментации Стандартные директивы сегментации изначально использовались для оформления программы в трансляторах MASM и TASM. Поэтому их называют стандартными директивами сегментации. Для простых программ, содержащих по одному сегменту для кода, данных и стека, хотелось бы упростить ее описание. Для этого в трансляторы MASM и TASM ввели возможность использования упрощенных директив сегментации. Но здесь возникла проблема, связанная с тем, что необходимо было как-то компенсировать невозможность напрямую управлять размещением и комбинированием сегментов. Для этого совместно с упрощенными директивами сегментации стали использовать директиву указания модели памяти MODEL, которая частично стала управлять размещением сегментов и выполнять функции директивы ASSUME (поэтому при использовании упрощенных директив сегментации директиву ASSUME можно не использовать). Директива MODEL связывает сегменты, которые в случае использования упрощенных директив сегментации имеют предопределенные имена, с сегментными регистрами (хотя явно инициализировать ds все равно придется). Пример программы с использованием упрощенных директив сегментации: ;---------------------------------------masm ;режим работы TASM: ideal или masm model small ;модель памяти .data ;сегмент данных message db 'Введите две шестнадцатеричные цифры,$' .stack ;сегмент стека db 256 dup ('?') ;сегмент стека .code ;сегмент кода main proc ;начало процедуры main mov ax,@data ;заносим адрес сегмента ;данных в регистр ax mov ds,ax ;ax в ds ;далее текст программы (см. сегмента кода в листинге 3.1 книги) mov ax,4c00h ;пересылка 4c00h в регистр ax int 21h ;вызов прерывания с номером 21h main endp ;конец процедуры main end main ;конец программы с точкой входа main Синтаксис директивы MODEL: Модификатор модели памяти Значение модификатора Назначение use16 Сегменты выбранной модели используются как 16битные (если соответствующей директивой указан процессор i80386 или i80486) use32 Сегменты выбранной модели используются как 32битные (если соответствующей директивой указан процессор i80386 или i80486) dos Программа будет работать в MS-DOS Модель памяти является обязательным параметром директивы MODEL. Этот параметр определяет модель сегментации памяти для программного модуля. Модели памяти Модель TINY SMALL MEDIUM Тип Тип кода данных near near far COMPACT near Назначение модели near Код, данные и стек объединены в одну группу с именем DGROUP и размером до 64Кб. Используется для создания программ формата .com. Некоторые языки эту модель не поддерживают. СS=DS=SS=DGROUP near Код занимает один сегмент, данные и стек объединены в одну группу с именем DGROUP (хотя для описания могут использоваться разные сегменты). Эту модель обычно используют для большинства программ на ассемблере. CS=_text DS=SS=DGROUP near Код занимает несколько сегментов, по одному на каждый объединяемый программный модуль. Все ссылки на передачу управления — типа far (вызов подпрограмм). Данные и стек объединены в одной группе DGROUP; все ссылки на них — типа near (для доступа к данным испльзуется только смещение). CS=<модуль>_text DS=SS=DGROUP far Код находится в одном сегменте, данные и стек в группе DGROUP и могут занимать несколько сегментов, так что для обращения к данным требуется указывать сегмент и смещение ( ссылка на данные — типа far). CS=_text DS=SS=DGROUP LARGE far far Код может занимать несколько сегментов, по одному на каждый объединяемый программный модуль. Стек и данные находятся в группе DGROUP. Для ссылки на данные используются дальние указатели -far. CS=<модуль>_text DS=SS=DGROUP HUGE far far Тоже что и модель LARGE, что касается TurboAssebmler. far Тоже, что и TINY, но используются 32-битная адресация, так что максимальный размер сегмента, содержащего и данные, и код, и стек 4Гб. FLAT far Предполагается, что программный модуль может иметь только определенные типы сегментов, которые определяются упомянутыми нами ранее упрощенными директивами описания сегментов. Эти директивы приведены в таблице ниже. Упрощенные директивы определения сегмента Формат директивы (режим MASM) Формат директивы (режим IDEAL) Назначение .CODE [имя] CODESEG[имя] Начало или продолжение сегмента кода .DATA DATASEG .CONST CONST .DATA? UDATASEG Начало или продолжение сегмента инициализированных данных. Также используется для определения данных типа near Начало или продолжение сегмента постоянных данных (констант) модуля Начало или продолжение сегмента неинициализированных данных. Также используется для определения данных типа near .STACK [размер] STACK [размер] .FARDATA [имя] FARDATA [имя] .FARDATA? [имя] UFARDATA [имя] Начало или продолжение сегмента стека модуля. Параметр [размер] задает размер стека Начало или продолжение сегмента инициализированных данных типа far Начало или продолжение сегмента неинициализированных данных типа far Наличие в некоторых директивах параметра [имя] говорит о том, что возможно определение нескольких сегментов этого типа. С другой стороны, наличие нескольких видов сегментов данных обусловлено требованием обеспечить совместимость с некоторыми компиляторами языков высокого уровня, которые создают разные сегменты данных для инициализированных и неинициализированных данных, а также констант. При использовании директивы MODEL транслятор делает доступными несколько идентификаторов, к которым можно обращаться во время работы программы, с тем, чтобы получить информацию о тех или иных характеристиках данной модели памяти. Идентификаторы, создаваемые директивой MODEL Имя идентификатора Значение переменной @code Физический адрес сегмента кода @data Физический адрес сегмента данных типа near @fardata Физический адрес сегмента данных типа far @fardata? Физический адрес сегмента неинициализированных данных типа far @curseg Физический адрес сегмента неинициализированных данных типа far @stack Физический адрес сегмента стека Если вы посмотрите на текст примера, то увидите пример использования одного из этих идентификаторов. Это @data – с его помощью мы получили значение физического адреса сегмента данных нашей программы. Необязательные параметры язык и модификатор языка определяют некоторые особенности вызова процедур. Необходимость в использовании этих параметров появляется при написании и связывании программ на различных языках программирования. Язык — необязательный операнд, принимающий значения C, PASCAL, BASIC, FORTRAN, SYSCALL и STDCALL. Если он указан, подразумевается, что процедуры рассчитаны на вызов из программ на соответствующем языке высокого уровня, следовательно, если указан язык C, все имена ассемблерных процедур, объявленных как PUBLIC, будут изменены так, чтобы начинаться с символа подчеркивания, как это принято в C. Модификатор — необязательный операнд, принимающий значения NEARSTACK (по умолчанию) или FARSTACK. Во втором случае сегмент стека не будет объединяться в одну группу с сегментами данных. После того как модель памяти установлена, вступают в силу упрощенные директивы определения сегментов, объединяющие действия директив SEGMENT и ASSUME. Кроме того, сегменты, объявленные упрощенными директивами, не требуется закрывать директивой ENDS — они закрываются автоматически, как только ассемблер обнаруживает новую директиву определения сегмента или конец программы. Директива .CODE описывает основной сегмент кода .code имя_сегмента эквивалентно: _TEXT segment word public ’CODE’ для моделей TINY, SMALL и COMPACT name_TEXT segment word public ’CODE’ для моделей MEDIUM, HUGE и LARGE (name — имя модуля, в котором описан данный сегмент). В этих моделях директива .CODE также допускает необязательный операнд — имя определяемого сегмента, но все сегменты кода, описанные так в одном и том же модуле, объединяются в один сегмент с именем NAME_TEXT. Директива .STACK описывает сегмент стека .stack размер эквивалентно: STACK segment para public ’stack’ Необязательный параметр указывает размер стека. По умолчанию он равен 1 Кб. Директива .DATA описывает обычный сегмент данных .data эквивалентно: _DATA segment word public ’DATA’ Директива .DATA? описывает сегмент неинициализированных данных .data? Эквивалентно: _BSS segment word public ’BSS’ Этот сегмент обычно не включается в программу, а располагается за концом памяти, так что все описанные в нем переменные на момент загрузки программы имеют неопределенные значения. Директива .CONST описывает сегмент неизменяемых данных .const Эквивалентно: CONST segment word public ’CONST’ В некоторых операционных системах этот сегмент будет загружен так, что попытка записи в него может привести к ошибке. Директива .FARDATA описывает сегмент дальних данных .fardata имя_сегмента эквивалентно: имя_сегмента segment para private ’FAR_DATA’ Доступ к данным, описанным в этом сегменте, потребует загрузки сегментного регистра. Если не указан операнд, в качестве имени сегмента используется FAR_DATA. Директива .FARDATA? описывает сегмент дальних неинициализированных данных .fardata? имя_сегмента эквивалентно: имя_сегмента segment para private ’FAR_BSS’ Как и в случае с FARDATA, доступ к данным из этого сегмента потребует загрузки сегментного регистра. Если имя сегмента не указано, используется FAR_BSS. Во всех моделях памяти сегменты, представленные директивами .DATA, .DATA?, .CONST, .FARDATA и .FARDATA?, а также сегмент, описанный директивой .STACK, если не был указан модификатор FARSTACK, и сегмент .CODE в модели TINY автоматически объединяются в группу с именем FLAT — для модели памяти FLAT или DGROUP — для всех остальных моделей. При этом сегментный регистр DS (и SS, если не было FARSTACK, и CS в модели TINY) настраивается на всю эту группу, как если бы была выполнена команда ASSUME. Порядок загрузки сегментов При использовании стандартных директив сегментации сегменты загружаются в память в том порядке, в котором они описываются в тексте программы. При использовании упрощенных директив сегментации (по умолчанию) устанавливается порядок загрузки сегментов, существующий в MS DOS и часто требуемый для взаимодействия программ на ассемблере с программами на языках высокого уровня. Порядок загрузки сегментов: 1. Все сегменты класса 'CODE'. 2. Все сегменты, не принадлежащие группе DGROUP и классу 'CODE'. 3. Группа сегментов DGROUP: 3.1. Все сегменты класса 'BEGDATA'. 3.2. Все сегменты, кроме классов 'BEGDATA', 'BSS' и 'STACK'. 3.3. Все сегменты класса 'BSS'. 3.4. Все сегменты класса 'STACK'. Знание порядка загрузки сегментов необходимо, например, для вычисления длины программы или адреса ее конца. Для этого надо знать, какой сегмент будет загружен последним, и смещение последнего байта в нем. P.S. В книге Зубкова, порядок загрузки сегментов описан несколько иначе, НО практика показала, что его описание не правильное. При использовании упрощенных директив сегментации, директива .seq, которая, по идее должна устанавливать порядок загрузки сегментов, как они описаны в прорамме, этого не делает! А делает это дериктива .alpha, и то, только при использовании TASM, только в модели small, и при этом она добавляет заголовок в exe файл длиной 600h байт! MASM же, при использовании упрощенных директив сегментации всегда размещает сегменты в соответствии с порядком MS DOS, забивая на директивы .seq и .alpha. И еще с выравниванием сегментов, при использовании упрощенных директив сегментации, происходит какая-то свистопляска :). Все это выявлено опытным путем. Все в следующих сериях супер сериала "Hello World". И так, жем вас у экранов мониторов :) АВТ ОР: - =* =- ЯРЛ Ы КИ: Д ИРЕКТ ИВА MOD EL , Д ИРЕКТ ИВ А SEGM ENT , СИНТ АКСИС АССЕМБЛЕРА НА 7:51 0 КОММЕНТ.: Отправить комментарий Следующее Предыдущее Главная страница