
3.7. Инициализация программы
Для инициализации ассемблерной ЕХЕ-программы необходимо выполнить четыре требования:
указать ассемблеру, какие сегментные регистры должны соответствовать сегментам;
сохранить в стеке адрес, находящийся в регистре DS, когда программа начнет выполнение;
записать в стек нулевой адрес;
загрузить в регистр DS адрес сегмента данных.
Выход из программы и возврат в операционную систему сводится к использованию команды RET.
Ассоциируя сегменты с сегментными регистрами, ассемблер определяет смещения к отдельным областям в каждом сегменте. Например, каждая команда в сегменте кодов имеет определенную длину: первая команда имеет смещение 0, и если это двухбайтовая команда, то вторая команда будет иметь смещение 2 и так далее.
Загрузочному модулю в памяти непосредственно предшествует 256-байтовая (0100Н) область, называемая префиксом программного сегмента РSР. Программа загрузчика использует регистр DS для установки адреса начальной точки PSP. Пользовательская программа должна сохранить этот адрес, поместив его в стек. Позже, команда RЕТ использует этот адрес для возврата в ОС.
В системе требуется, чтобы следующее значение в стеке являло нулевым адресом (точнее, смещением). Для этого команда SUB очищает регистр АХ, вычитая его из этого же регистра АХ, а команда PUSH заносит это значение в стек.
Загрузчик ОС устанавливает правильные адреса стека в регистре SS и сегмента кодов в регистре СS. Поскольку программа загрузчика использует регистр DS для других целей, необходимо инициализировать регистр DS двумя командами МОV.
Команда RET обеспечивает выход из пользовательской программы и возврат в ОС, используя для этого адрес, записанный в стек в начале программы командой PUSH DS. Другим обычно используемым выходом является команда INT 020Н.
Системный загрузчик при загрузке программы с диска в память для выполнения устанавливает действительные адреса в регистрах SS и CS. Программа не имеет сегмента данных, так как в ней нет определения данных и, соответственно, в директиве ASSUME нет необходимости использовать регистр DS.
Команды SUB и PUSH выполняют стандартные действия для занесения в стек текущего адреса из регистра DS и нулевого адреса. Поскольку, обычно, программа выполняется из ОС, то эти команды обеспечивают возврат в ОС после завершения программы.
3.8. Логика организации программы
Можно рекомендовать следующий порядок написания программы в среде ассемблера:
Четко сформулировать задачу, которую должна решить программа
Сделать эскиз задачи в общих чертах и спланировать общую логику программы
Представить программу в виде логических блоков, следующих друг за другом. Процедуры не превышающие 25 строк (размер экрана в среде ассемблера) удобнее для отладки.
Необходимо активно пользоваться открытыми тестовыми примерами программ и их фрагментами. Множество ошибок может возникнуть из-за значительного количества технических деталей при программировании сложных программ.
Необходимо активно использовать комментарии для описания того, что будет делать та или иная процедура, какие арифметические действия или операции над строковыми последовательностями будут выполняться, что делают редко используемые команды и т.п.
Для кодирования программы желательно использовать заготовку программы, скопированную в файл с новым именем.
Кроме того, следует помнить следующие рекомендации во время работы с ассемблером:
- необходимо ставить символ «точка с запятой» перед комментариями;
- завершать каждый сегмент директивой ENDS, каждую процедуру - директивой ENDP, а программу – директивой END;
- в директиве ASSUME устанавливаются соответствия между сегментными регистрами и именами сегментов;
- для ЕХЕ-программ необходимо обеспечивать не менее 32 слов для стека, соблюдать соглашения по инициализации стека командами PUSH, SUB и PUSH и заносить в регистр DS адрес сегмента данных.
- метки процедур должны завершаться двоеточием для указания типа NЕАК, отсутствие двоеточия приводит к ассемблерной ошибке;
- метки для команд условного перехода и LOOP должны лежать в границах -128 до +127 байт;
- при использовании команды LООР, регистр СХ должен инициализироваться положительным числом. Команда LООР контролирует только нулевое значение, при отрицательном будет продолжать выполняться цикл;
- в случае, если некоторая команда устанавливает флаг, то данный флаг сохраняет это значение, пока другая команда его не изменит. Например, если за арифметической командой, которая устанавливает флаги, следуют команды МОV, то они не изменят флаги. Однако, для минимизации числа возможных ошибок, следует кодировать команды условного перехода непосредственно после команд, устанавливающих проверяемые флаги;
- необходимо выбирать команды условного перехода соответственно операциям над знаковыми или беззнаковыми данными;
- для вызова процедуры используется команда САLL, а для возврата из процедуры — команда RET, вызываемая процедура может, в свою очередь, вызвать другую процедуру, и если следовать существующим соглашениям, то команда RЕТ всегда будет выбирать из стека правильный адрес возврата.