Сегменты упрощенной модели памяти Small
Ассемблер использует те же модели памяти, что и языки высокого уровня · Имя – идентификатор данного сегмента, используемый при назначении адреса и комбинировании (объединении) с другими сегментами. · Выравнивание – указывает граничные значения на начало сегмента. В процессе ассемблирования, если текущая позиция в начале сегмента не удовлетворяет установленному атрибуту, счётчик адреса увеличивается на соответствующую величину, смещая начало сегмента в область старших адресов (word – начало сегмента должно иметь чётный адрес, para – чётный адрес, кратный параграфу, т.е. 16 бит) · Объединение – устанавливает правила объединения нескольких сегментов с одинаковым именем. Параметр Public приводит к последовательному объединению сегментов с одинаковым именем в один большой сегмент, имеющий адрес первого из объединяемых сегментов. · Класс – выполняет роль категории сегмента. Все сегменты одинакового класса во время работы компоновщика физически располагаются друг за другом в памяти · Группа – позволяет осуществить доступ к данным из всех сегментов, находящихся в ней, с помощью загрузки адреса группы в сегментный регистр. Наибольшее применение в ассемблерных программах с расширением .exe нашла малая модель памяти Model small, предусматривающая размещение структурных частей программы в двух сегментах: · сегмент кода программы (64 Кбайт), · сегмент данных и стека, принадлежащих одной группе Dgroup (64 Кбайт). Шаблон программы для exe -файлов с подробными комментариями представлен на рис. 1.1. Здесь отметим лишь оформление начала и конца кодового сегмента. Для того чтобы понять, почему кодовый сегмент начинается с загрузки сегментного регистра данных ds, а не с загрузки сегментного регистра cs, необходимо рассмотреть функции DOS при загрузке программы в память. %Title " Имя EXE -файла программы" Ideal; Переводит Turbo Assembler в режим Ideal Model small; Директива описания модели памяти. Вводит упрощенные директивы ; управления сегментами P486N; Разрешает инструкции старших поколений процессоров. При её ; отсутствии действует по умолчанию P8086. Разрешает использование ; 32 – разрядных регистров для адресации и хранения данных Stack 256; Резервирует пространство для стека программы (значение в байтах, ; следующее за директивой) ; 1. Здесь следует располагать макроопределения EQU и = ; 2. Вставьте здесь директиву Include " filename" Dataseg; Начало сегмента инициализированных данных. Допускается также ; расположение здесь и неинициализированных данных, начальные ; значения которых неизвестны на момент запуска программы ; 1. Здесь описываются переменные с помощью директив DB, DW и т. п. ; 2. Здесь опишите все переменные типа Extrn Codeseg; Начало сегмента кода, т.е. части программы, содержащей команды ; процессора. ; Здесь определите все подпрограммы типа Extrn Start: mov ax, @data; Точка начала исполнения программы mov ds, ax; Установка в регистре DS адреса сегмента данных ; Здесь располагается программа, вызовы подпрограмм и т. п. Exit: mov ax, 4C00h; Функция DOS: Выход из программы int 21h; Вызов DOS. Останов программы End Start; Директива конца программы/точки входа. Текст, ; расположенный после этой строки будет игнорироваться ассемблером. Рис. 1.1. Шаблон структуры программы типа .exe Образ программы в памяти [Л: 4, 12, 13, 14], представленный на рис. 1.2[4], начинается с префикса программного сегмента PSP (Program Segment Prefix). PSP всегда имеет размер 256 байтов и содержит данные, используемые операционной системой в процессе исполнения программы. Вслед за PSP располагаются сегменты программы. Сегментные регистры es и ds автоматически инициализируются на начало PSP. Это даёт возможность, при сохранении значения одного из регистров, обращаться к PSP в случае необходимости. В указатель команд ip загружается относительный адрес точки входа в программу (операнд директивы END), а в указатель стека sp -смещение конца сегмента стека. Таким образом, после загрузки программы в память, адресуемыми являются все сегменты, кроме сегмента данных. Использование директивы Model, делает доступным ассемблеру несколько служебных идентификаторов, к которым можно обращаться во время работы программы, чтобы получить информацию об адресах используемых сегментов. Например: @code – 16-разрядный адрес сегмента кода, @data – 16-разрядный адрес сегмента данных типа near, @stack – 16-разрядный адрес сегмента стека.
Объём памяти, занимаемый программой: (138B-1373)*10h+100h=280h=640 байт
Рис. 1.2. Образ программы hello.exe в памяти, загруженной командой Td hello.exe
Вот поэтому-то имя предопределённого идентификатора @data и используется в первой паре команд кодового сегмента для загрузки сегмента данных. Завершение программы означает передачу управления командному процессору DOS – Command.com, который выводит на экран системный запрос в ожидании следующей команды от оператора. Делается это с помощью функции DOS (ah = 4Ch). Эта функция требует единственного параметра – кода возврата, который и помещается программой в регистр al. Если этот код равен нулю, то исполнение программы прошло корректно, в противном случае была допущена ошибка в предшествующих обращениях программы к другим системным функциям DOS. В некоторых случаях для создания компактных программ (прежде всего это резидентные программы) бывает удобным не дробить программу на отдельные сегменты. Этой цели в наибольшей мере отвечают программы типа .com, которые состоят лишь из одного сегмента, включающего все компоненты программы. Шаблон программы типа .com приведён на рис. 1.3. При компоновке программы необходимо использовать опцию /t, которая указывает на создание файла .com вместо .exe. Образ памяти программы типа .com показан на рис. 1.4. После загрузки программы в память все 4 сегментных регистра указывают на начало единственного сегмента – PSP. Указатель стека автоматически инициализируется числом 0FFFEh. Таким образом, независимо от фактического размера программы, ей выделяется 64 Кбайт адресного пространства, нижнюю часть которого занимает стек.
%Title " Имя com – файла программы" Ideal
|