Оформление и размещение в памяти ассемблерных программ
Тексты исполняемых программ могут быть представлены в ЕХЕ- или СОМ форматах. Различие между программами в ЕХЕ- и СОМ-файлах заключается в следующем. Размер программы. Программа в ЕХЕ может иметь любой размер, в то время как СОМ-файл ограничен размером одного сегмента (≤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 располагается буфер передачи данных, который используется как буферная область ввода/вывода для текущего дисковода
Схема размещение СОМ-программы в памяти показано на рисунке 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 Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...
|