Главная | Обратная связь | Поможем написать вашу работу!
МегаЛекции

Оформление и размещение в памяти ассемблерных программ




Тексты исполняемых программ могут быть представлены в ЕХЕ- или СОМ форматах. Различие между программами в ЕХЕ- и СОМ-файлах заключается в следующем.

Размер программы. Программа в ЕХЕ может иметь любой размер, в то время как СОМ-файл ограничен размером одного сегмента (≤64к). Размер СОМ-файла всегда меньше, чем размер соответствующего ЕХЕ-файла, так как в СОМ-файле отсутствует заголовок (512 байт) ЕХЕ-файла. Заголовок хранится на диске в начале ехе-файла. В заголовке содержится информация о размере выполняемого модуля, области загрузки в памяти, адрес стека и относительное смещение. В нем также указывается число байтов в последнем блоке ехе-файла, число настраиваемых параметров, количество параграфов в заголовке и некоторые другие данные.

Сегмент стека. В ЕХЕ следует задавать сегмент стека, в то время как СОМ-программа генерирует стек автоматически.

Сегмент данных. В ЕХЕ-программах обычно определяется сегмент данных, а регистр DS инициализируется адресом этого сегмента. В СОМ-программах все данные должны быть определены в сегменте кода.

Инициализация. В ЕХЕ-программе следует записать 0-слово в стек и инициализировать регистр DS. Так как в СОМ стек и сегмент данных не определены, то эти шаги отсутствуют.

При запуске СОМ-программы сегментные регистры содержат адрес префикса программного сегмента (256 байт=100Н), который резервируется DОS непосредственно перед СОМ- или ЕХЕ –программой в памяти. Так как адресация начинается со смещения 100Н от начала префикса, то в программе после директивы SEGMENT следует вносить директиву ORG 100H.

Для преобразования ЕХЕ-файла в СОМ-файл используется программа ЕХЕ2BIN.

Если в программе отсутствует явное объявление стека, то система сама создает стек по умолчанию в конце сегмента команд. Эот объясняется следующим образом. Если запустить программу, то можно увидеть (с помощью отладчика), что в SS находится тот же адрес, что и в CS, а в SP=0. Первая же команда PUSH уменьшает содержание SP на 2, то есть поместит в SP-2 которое равно FFFEh (0-2). При дальнейшей записи в стек его указатель будет смещаться в сторону меньших адресов. При интенсивном использовании стека в программе может получиться, что стек дорастет до последних команд сегмента команд и начнет затирать эти команды. В связи с этим следует использовать отдельный сегмент стека SS.

При размещение.ЕХЕ-программы в памяти регистры CS и SS указывает на начало сегмента команд (DOS делает автоматически). Поскольку сегмент данных оказывается не адресуемым, то необходимо инициализировать регистр DS (и ES).

 

begin: mov ax, data; data – начало сегмента данных

mov ds, ax

push DS

pop ES

.

mov ax, 4c00h; функция завершения программы

int 21h; вызов DOS

 

Префикс программного сегмента PSP: первые два байта префикса программного сегмента содержат команду INT20h завершение программы (DOS восстанавливает векторы критических прерываний по значениям, хранящимся в PSP; очищает буфер файлов и передает управление процедуре завершения). Затем указывается общий размер доступной памяти XXXXOh.

Программа в памяти начинается с префикса программного сегмента (PSP), который образуется и заполняется DOS в процессе загрузки программы в память. Затем в памяти располагаются сегменты в том порядке, как они объявлены в тексте программы (рисунок 5.11а).

 

В процессе загрузки в память сегментные регистры автоматически инициализируется следующим образом: ES и DS указывают на начало PSP. Поэтому перед началом выполнения программы нужно сохранить их значения, чтобы после окончания можно было обратиться к PSP. Потом размещается адрес подпрограммы завершения, а также адреса п/п реакции на Ctrl/Break, на фатальную ошибку.

В ячейках с 80 по FF располагается буфер передачи данных, который используется как буферная область ввода/вывода для текущего дисковода

   
а) б)
Рисунок 6.11 – Схема размещения программ ЕХЕ (а) и СОМ (б) в памяти  

Схема размещение СОМ-программы в памяти показано на рисунке 5.11б. Под команды, данные и стек выделяется только один сегмент. В начале сегмента размещается префикс программного сегмента PSP. Заполняет PSP операционная система DOS, но место под него в начале программы должен зарезервировать программист. В программе нет необходимости инициализировать регистр DS, поскольку его, как и другие сегментные регистры инициализирует ОС.

 

Пример 1 программы на ассемблере МП 8086.

NAME EXAMPLE

ASSUME CS: CODE, SS: STACK, DS: DATA

DATA SEGMENT

VAR-1 DW 0; определить и инициализировать

VAR-2 DW 0; две переменные

DATA ENDS

 

STACK SEGMENT

DW 10DUP(?); зарезервировать 10 слов

STK_TOP LABEL WORD; вершина стека

STACK ENDS

 

CODE SEGMENT

START: MOV AX, DATA; инициализация регистров DS и SS

MOV DS,AX

MOV AX, STACK

MOV SS, AX

MOV SP, OFSET STK_TOP

PROG: PUSH AX; заполнить (AX)

MOV AX, VAR-1; увеличить на 5 значение VAR-1

ADD AX,5

MOV VAR-2, AX; присвоить VAR-2

POP AX; восстановить AX

CODE ENDS

END START; конец исходного модуля

 

В первой строке программы находится директива NAME (наименовать), которая присваивает внутреннее имя объектному модулю, генерируемому ассемблером. Имя модуля EXAMPLE нельзя путать с именем файла – оно хранится внутри объектного файла.

Программа состоит из трех различных логических сегментов DATA, STACK, CODE. Каждый сегмент начинается с директивы SEGMENT и заканчивается директивой ENDS, причем обе директивы для одного и того же сегмента имеют одинаковые имена. Логические сегменты соответствуют физическим сегментам в памяти, но привязки логических сегментов к физическим адресам памяти в этом исходном модуле нет.

Директива ASSUME сообщает ассемблеру, что регистр CS будет содержать базовый адрес сегмента CODE, а регистр DS – базовый адрес сегмента DATA. Регистр ES не используется, поэтому указание о нем в директиве отсутствует.

Сегмент данных DATA содержит всего две переменные, которые инициализированы с помощью директив DW. В сегменте STACK резервируются 10 слов памяти, т.е. для стека в программе резервируется 10 слов (глубина стека 10 слов). Директива LABEL (отметить) определяет имя STK_TOP, которое идентифицирует вершину пока пустого стека.

Сегмент кода начинается с пяти команд, обеспечивающих инициализацию сегментных регистров и указателя стека SP. Выражение OFFSET STK_TOP представляет собой смещение метки STK_TOP от начала содержащего ее сегмента STACK. Собственно программа начинается с метки PROG. Директива END с операндом START сообщает ассемблеру о достижении конца исходного модуля и необходимости начать выполнение программы с команды, отмеченной меткой START.

Пример 2 ассемблерной программы:

Page 60, 132

TITLE EXAMPLE (EXE)

;--------------------------------------------

STACKSG SEGMENT PARA STACK ‘stack’; Указывать обязательно, т.к. по ней осуществляется.; автомати ческая инициализация SS и SP

; Если тип объединения STACK, то при компоновке; одноименные сегменты располагаются рядом, при;COMMON – накладываются друг на друга

DW 10 DUP(?);

STACKSG ENDS

;--------------------------------------------------------------------------------------

DATASG SEGMENT PARA ‘Data’

NAME1 DB ‘ASSEMBLERS’;

NAME2 DB 10DUP(‘ ‘); зарезервировать 10 слов

DATASG ENDS

;--------------------------------------------------------------------------------

; --------------------------------------------------------------------------------------

CODESG SEGMENT PARA ‘Code’; для правильной работы LINK необходимо указать ‘Code’

BEGIN PROC FAR

 

ASSUME CS:CODESG; DS:DATASG, SS:STACKSG, ES:DATASG

; Показывает транслятору, какие регистры закрепляются за

; сег ментами, которые затем используются по умолчанию

PUSH DS; записать DS в стек

SUB AX, AX; записать 0 в стек

PUSH AX

MOV AX, DATASG; регистры CS и SS инициализируются автоматически

MOV DS, AX

MOV ES, AX

; --------------------------------------------------------------------------------------------------------

MOV AX, 0123H

ADD AX, 0025H

MOV BX, AX

ADD BX, AX

SUB AX, AX

NOP

; ---------------------------------------------------------------------------------------------------------

CLD

LEA SI, NAME1

LEA DI, NAME2

MOV CX, 10

REP MOUSB; переслать 10 байтов из NAME1 NAME2

; ----------------------------------------------------------------------------------------------------------

RET; возврат в DOS

BEGIN ENDP

CODESG ENDS

END [BEGIN]; операнд может быть опущен, если эта программа должна быть скомпонована

;с другим (главным) модулем. Для обычных программ операнд содеожит имя, указанное в;директивве PROG, (то есть в точку входа в главную процедуру). Этим адресом

; загружается IP.

 

Программа в формате ЕХЕ, созданная компоновщиком, состоит из следующих двух частей: 1) заголовка – записи, содержащей информацию по управлению и настройке программы, и 2) собственно загрузочного модуля.

В заголовке находится информация о размере выполняемого модуля, области загрузки в памяти, адресе стека и относительных смещениях, которые должны заполнить машинные адреса в соответствии с относительными 16-ричными позициями.

Заголовок имеет минимальный размер 512 байт и может быть больше, если программа содержит большое число настраиваемых элементов. Позиция 06 в заголовке указывает число элементов в выполняемом модуле, нуждающихся в настройке. Каждый элемент настройки в таблице, начинающейся в позиции 1С заголовка, состоит из двухбайтовых величин смещений и двухбайтовых сегментных значений.

Операционная система строит префикс программного сегмента (PSP) следом за резидентной частью COMMAND.COM, которая выполняет операцию загрузки. Затем COMMAND.COM осуществляет следующее:

§ Считывает форматированную часть заголовка в память;

§ Вычисляет размер выполнимого модуля (общий размер файла в позиции 04 минус размер заголовка в позиции 08) и загружает модуль в память с начала сегмента;

§ Считывает элементы таблицы настройки в рабочую область и прибавляет адрес начала сегмента;

§ Устанавливает в регистрах SS и SP значения из заголовка и прибавляет адрес начала сегмента;

§ Устанавливает в регистрах DS и ES сегментный адрес префикса программного сегмента;

§ Устанавливает в регистре CS адрес PSP и прибавляет величину смещения в заголовке (позиция 16) к регистру CS. Если сегмент кода непосредственно следует за PSP, то смещение в заголовке равно 256 (100h). Регистровая пара CS:IP содержит стартовый адрес в кодовом сегменте, т.е. начальный адрес программы.

После инициализации регистры CS и SS содержат правильные адреса сегментов, а регистр DS (и ES) должен быть настроен в программе на собственный сегмент данных.

При завершении программы команда RET заносит в регистр IP нулевое значение, которое было помещено в стек в начале выполнения программы. В регистровой паре CS:IP в этом случае получается адрес, который является адресом первого байта PSP, где расположена команда INT 20h. Когда эта команда будет выполнена, управление перейдет в DOS.

 

Пример 3 оформления СОМ-программы

Page 60,80

TITLE EXAMPLE_COM для пересылки и сложения

Codes SEGMENT PARA ‘Code’

ASSUME CS:CODESG, DS:CODESG, SS:CODESG, ES:CODESG

ORG 100H; начало в конце PSP

BEGIN: JMP MAIN; обход через данные

;---------------------------------------------------------------------------------

ALPHA DW 250

BETA DW 125

GAMMA DW?

;---------------------------------------------------------------------------------

MAIN PROC NEAR

MOV AX, ALPHA

ADD AX, BETA

MOV GAMMA, AX

RET; вернуться в DOS

; можно вместо RET INT20H

MAIN ENDP

Codes ENDS

END BEGIN

 

В отличие от ЕХЕ-файла СОМ-файл не содержит заголовка на диске. Так как организация СОМ-файла намного проще, то для DOS необходимо знать только то, что тип файла СОМ. Как уже упоминалось выше, загруженным в память СОМ- и ЕХЕ-файлам предшествует префикс программного сегмента. Первые два байта этого префикса содержат команду INT20h (возврат в DOS).

При загрузке СОМ-программы DOS устанавливает в четырех сегментных регистрах адрес первого байта PSP. Затем устанавливается указатель стека на конец сегмента объемом 64 Кбайт (FFFE), т.е. на конец памяти. В вершину стека заносится нулевое слово. В командный указатель помещается 100Н (размер PSP). После этого управление передается по адресу регистровой пары CS:IP, т. е. на адрес непосредственно после PSP. Этот адрес является началом выполняемой СОМ-программы и должен содержать выполнимую команду.

При выходе из программы команда RET заносит в регистр IP нулевое слово, которое было записано в вершину стека при инициализации. В этом случае в регистровой паре CS:IP получается адрес первого байта PSP, где находится команда INT20h. При выполнении этой команды управление передается в резидентную часть COMMAND.COM. Если программа завершается по команде INT20h (Завершение программы, управление передается DOS) вместо RET, то управление непосредственно передается в COMMAND.COM.

Примечание.

Коды команд, данные и стек в СОМ-программах располагаются в одном сегменте. Вследствие этого СОМ-программа занимает в памяти 64 Кбайт, независимо от ее размера на диске. Этот факт является одной из причин предпочтительного использования ЕХЕ-формата.

Хотя ЕХЕ-файл может занимать больше дискового пространства (т.к. в него включена дополнительная информация), небольшие ЕХЕ-программы занимают при исполнении в памяти значительно меньше места, чем эквивалентные им СОМ-программы.

СОМ-формат файла наследуется из ОС СР/М. Полезный в ряде случаев, формат не рекомендуется использовать для РС-программ.

Команды СОМ-программ загружаются в память с адреса 100h относительно начала кодового сегмента программы. По такому же адресу загружаются программы в ОС СР/М, на которой во многом основана DOS и которая используется в компьютерах, имеющих 64К общей памяти. Под управлением DOS СОМ-программы работают в режиме псевдо-СР/М адресного пространства, несмотря на то, что современные компиляторы имеют объем памяти в десятки раз больший. Т.о. сегодня уже нет разумных причин для этого устаревшего формата файла.

Компания Microsoft объявила о своем намерении отказаться от использования СОМ-фор­мата, хотя эти попытки не являются успешными.


Поделиться:





Воспользуйтесь поиском по сайту:



©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...