Создание com и exe их структурное отличие на примере сегментов памяти

Обновлено: 09.05.2024

Постановка задачи.

Таблица 1 – функции в программе

Перевод десятичной цифры в код символа

Перевод байта в 16-ной с/с в символьный код

Перевод слова в 16-ной с/с в символьный код

Перевод байта в 16-ной с/с в символьный код в 10-ной с/с

Вывод строки на экран

Определение типа PC

Определение характеристик OS

Выполнение работы.

Были объявлены строки для вывода информации:

TYPE_PC db 'Type: PC',0DH,0AH,'$';

TYPE_PC_XT db 'Type: PC/XT',0DH,0AH,'$';

TYPE_AT db 'Type: AT',0DH,0AH,'$';

TYPE_PS2_M30 db 'Type: PS2 модель 30',0DH,0AH,'$';

TYPE_PS2_M50_60 db 'Type: PS2 модель 50 или 60',0DH,0AH,'$';

TYPE_PS2_M80 db 'Type: PS2 модель 80',0DH,0AH,'$';

TYPE_PС_JR db 'Type: PСjr',0DH,0AH,'$';

TYPE_PC_CONV db 'Type: PC Convertible',0DH,0AH,'$';

VERSIONS db 'Version MS-DOS: . ',0DH,0AH,'$';

SERIAL_NUMBER db 'Serial number OEM: ',0DH,0AH,'$';

USER_NUMBER db 'User serial number: H $'.

Были составлены функция для определения типа ПК PC_TYPE в соответствии с таблицей:


А также функция для определения характеристик ОС OS_VER:

номер основной версии системы и её модификации;

серийный номер пользователя.


В результате выполнения были получены следующие значения(рис.1-3):

Рисунок 2 – «плохой» .EXE модуль


Рисунок 3 – «хороший» .EXE модуль

ПРИЛОЖЕНИЕ А

ОТВЕТЫ НА КОНТРОЛЬНЫЕ ВОПРОСЫ

Отличия исходных текстов COM и EXE программ:

Сколько сегментов должна сдержать COM-программа?

COM-программа должна содержать ровно один сегмент. Код и данные находятся в одном сегменте, а стек генерируется автоматически.

EXE-программа должна содержать не менее одного сегмента. Сегменты кода, данных и стека описываются отдельно друг от друга, но есть возможность не описывать сегмент стека, в таком случае будет использоваться стек DOS.

Какие директивы должны быть обязательно в тексте COM-программы?

Должна быть обязательна директива ORG 100h, так как при загрузке модуля все сегментные регистры содержат адрес префикса программного сегмента (PSP), который является 256-байтовым(100H) блоком, поэтому адресация имеет смещение в 256 байт от нулевого адреса. Также необходима процедура ASSUME для того, чтобы сегмент данных и сегмент кода указывали на один общий сегмент. (ASSUME CS:TESTPC, DS:TESTPC, ES:NOTHING, SS:NOTHING)

Все ли форматы команд можно использовать в COM-программе?

COM-файл состоит из одного сегмента, состоящего из сегмент кода и сегмент данных, сегмент стека генерируется автоматически при создании COM-программы. СОМ-файл ограничен размером одного сегмента и не превышает 64 Кб

Код начинается с адреса 0h, но при загрузке модуля устанавливается смещение в 100h.


Какова структура файла «плохого» EXE? С какого адреса располагается код? Что располагается с адреса 0?

В «плохого» EXE данные и код располагаются в одном сегменте, что для EXE файла некорректно, так как код и данные должны быть разделены на отдельные сегменты. Код располагается с адреса 300h, а с адреса 0h идёт таблица настроек.


Какова структура «хорошего» EXE? Чем он отличается от файла «плохого» EXE?


Загрузка COM модуля в основную память:

Какой формат загрузки модуля COM? С какого адреса располагается код?

Определяется сегментный адрес участка ОП, у которого достаточно места для загрузки программы, образ COM-файла считывается с диска и помещается в память, начиная с PSP:0100h. После загрузки двоичного образа COM-программы сегментные регистры CS, DS, ES и SS указывают на PSP(в данном случае сегментные регистры указывают на 48DD), SP указывает на конец сегмента PSP(обычно FFFE), слово 00H помещено в стек, IP содержит 100H в результате команды JMP PSP:100H.


Что располагается с адреса 0?

Программный сегмент PSP, размером 256 байт (100h), зарезервируемый операционной системой.

Какие значения имеют сегментные регистры? На какие области памяти они указывают?

Cсегментные регистры CS, DS, ES и SS указывают на PSP и имеют значения 48DD.

Как определяется стек? Какую область памяти он занимает? Какие адреса?

Стек генерируется автоматически при создании COM-программы. SS – на начало (0h), регистр SP указывает на конец стека (FFFEh), Адреса стека расположены в диапазоне 0h – FFFEh (FFFEh, – последний адрес, кратный двум).

Загрузка «хорошего» EXE модуля в основную память:

Как загружается «хороший» .EXE? Какие значения имеют сегментные регистры?

EXE-файл загружается, начиная с адреса PSP:0100h. В процессе загрузки считывается информация заголовка (PSP) EXE в начале файла и выполняется перемещение адресов сегментов, то есть DS и ES устанавливаются на начало сегмента PSP(DS=ES=48DD), SS(SS=48ED) – на начало сегмента стека, CS(CS=490D) – на начало сегмента команд. В IP загружается смещение точки входа в программу, которая берётся из метки после директивы END. Причём дополнительный программный сегмент (PSP) присутствует в каждом EXE-файле.


На что указывают регистры DS и ES?

Регистры DS и ES указывают на начало сегмента PSP.

Как определяется стек?

Стек определяется с помощью директивы .stack, после которой задаётся размер стека. При исполнение регистр SS указывает на начало сегмента стека, а SP на конца стека(его смещение).

Как определяется точка входа?

Точка входа определяется при помощи директивы END.

Тут вы можете оставить комментарий к выбранному абзацу или сообщить об ошибке.


Навигация сайта

Структура COM и EXE файлов

Структура COM файла

В основном COM файлы пишут на языке Ассемблера, но это не обязательно. Нописать файл можно на любом языке, который можно потом компилировать.

.286 ; Устанавливаем тип процессора
mov ah,09h ;Функцию DOS (прерывание 21h) 09h
mov dx,offset message ; Заносим в dx значение переменной message
int 21h ;Устанавливаем прерывание которое должно обработать функцию 09h

mov ah,4Ch ;Функцию DOS (прерывание 21h) 4Ch
int 21h ;Устанавливаем прерывание которое должно обработать функцию 00h

message db "My first COM programms",13,10,"$" ;Придаем значение переменной message

Использую определение прерывания можно сказать как действует эта программа.

mov ah,09h
int 21h

В первой строке в регистр ah заносится значение 09, где h означает, что это число в шестнадцатеричной системе исчисления, во второй строке указывается прерывание, в данном случае это 21, (h тоже самое, что и в первой строке) т.е. прерывание DOS. Получив такую команду, процессор на время перестает выполнять текущие операции и передает управление находящейся в оперативной памяти программе, обработчику функции 09h. После выполнения всех этих операций процессор возвращается к выполнению ранее выполняемой операции.

Ниже приведены два варианта кода COM - файла до "инфицирования" вирусом и после:

.286 ;Задаем тип процессора
code segmen ; Начало сегмента кода программы
org 100h ;Все COM программы начинаются с адреса 100h

jmp coob ; Тело программы начинается с метки coob

mov ah,4Ch
int 21h

coob: ;Начало тела программы
mov ah,09h ; Заносим значение 09h в регистр ah
mov dx,offset message ; В регистре dx указываем адрес строки с текстом
int 21h ; Указываем, что это прерывание DOS 21h

message db "Файл не инфицирован",13,10,"$" ; Строка с текстом для вывода на экран

mov ah,4Ch ;Выходим из программы
int 21h ; Прерывание 21h

ends code ; Конец сегмента кода программы

.286 ;Задаем тип процессора
code segmen ; Начало сегмента кода программы
org 100h ;Все COM программы начинаются с адреса 100h

jmp virus ; JMP изменены таками образом, чтобы вирус получил управление

mov ah,4Ch
int 21h
coob:
mov ah,09h
mov dx,offset message
int 21h
message db "Файл не инфицирован",13,10,"$" ; Строка с текстом для вывода на экран
mov ah,4Ch
int 21h

virus:

mov .
. > Вирус размножается и выполняет свои разрушительные действия
. int 21h

jmp coob

ends code ; Конец сегмента кода программы

Ниже приведена структура инфицированного файла

Хвост COM программы

Тело вируса

Оригинальное начало
COM программы

Структура EXE файла

COM файлы пишут в основном на языке Ассемблера, но они постепенно устаревают и на смену им приходят огромные по своим размерам и сложные по своей структуре EXE файлы.
Состоять EXE файлы могут из нескольких сегментов, следовательно их размер не ограничен 64 кб. По структуре EXE файл сложнее, кроме кода программы в файле также содержется: заголовок файла, таблица настройки адресов, данные и т.п.

Примерная структура EXE файла:

Тело программы

Конец программы

Заголовок EXE файла - содержет данные необходимые для загрузки программы
Тело программы - основная часть программы, выполняющая какие-либо полезные действия
Конец программы - завершающая часть программы, которая сохраняет нужные и удаляет ненужные данные из ОЗУ, закрывает все открытые данной программой файлы и т.п.

Первая и последняя часть программы являются обязательными для всех EXE файлов, а вторая часть вовсе не обязательна. Вы можете просто взять её и пропустить.

Приводить виды "инфицированного" и "не инфицированного" EXE файла я не буду, т.к. в отличие от COM вирусов, у EXE вирусов есть множество способов заражения. Подробно о каждом из них я расскажу Вам в следующих выпусках рассылки, а сейчас только перечислю названия основных из них:

OVERWRITE - вирусы, замещающие программный код

COMPANION - вирусы-спутники

PARASITIC - вирусы, внедряющиеся в программу

метод переименования EXE файла

внедрение способом переноса

внедрение способом сдвига

Стандартный вирус

Не только файлы имеют определенную структуру, но и вирусы для осуществления своей вредоносной деятельности должны соблюдать определенную структуру своего тела и действовать в определенном порядке.
Данная рассылка полна биологических и медицинских терминов, т.к. способы заражения, методы распространения компьютерных вирусов очень схожи с биологическими вирусами. Даже первый вирус создавался по аналогии с биологическими вирусами.

Интересно, а кто создал первый вирус ?

С момента появления вычислительной техники программистов и электронщиков интересовала одна тема: самовопроизводяющиеся и самораспространяющиеся механизмы. Первым кто попробовал осуществить эту идею в 1951 году был Дж. фон Нейман. Но Нейман и не думал использовать эти материалы в каких либо разрушительных целях, но другие люди, воспользовавшись его материалами и знаниями в этой области начали создавать различных вредоносные программы - компьютерные вирусы. Но что же побудило этих людей пойти на это. Ученые считают, что людей побуждают создавать компьютерные вирусы некоторые факторы:

- озорство и одновременное непонимание всех последствий распространения вируса
- стремление навредить кому-либо
- неестественная потребность в совершение преступлений
- желание самоутвердиться
- невозможночть использовать свои знания в правильном русле

Как и у биологических, у компьютерных вирусов есть определенные стадии "развития":

- латентный период - в течение которого вирус себя никак не проявляет (для того, чтобы "замести следы" источника его попадания на "инфицированный" ПК)
- инкубационный период - в рамках которого вирус только размножается
- период проявления - в течение которого вирус выполняет несанкционированные пользователем действия.
Компьютерные вирусы классифицируют по следующим признакам.
- способ обитания
- способ заражения и среды обитания
- способ активизации
- способ проявления
- способ маскировки

Нелепо думать, что компьютерные вирусы могут содержаться везде. Особенно это проявляется на пользователях "чайниках" которые могут часами просиживать перед экраном и с упортством проверять файлы, которые никак не могут содержать вирусы. Ведь вирус - это программа, следовательно имеет смысл внедряться только в другие программы. В связи с этим компьютерные вирусы подразделяют еще на:
- файловые
- загрузочные
- файлово-загрузочные вирусы

ФАЙЛОВЫЕ

Вирусы могут внедряться в следующие компоненты системы:

- файлы с компонентами DOS
- исполняемые файлы COM
- исполняемые файлы EXE
- внешние драйвера устройств (SYS- и BIN-файлы)
- объектные модули (OBJ-файлы)
- файлы программы до их компиляции, в надежде на то, что их когда нибуть компилируют и запустят
- командные файлы (BAT-файлы)
- файлы-библиотеки (LIB, DLL и др.файлы)
- оверлейные файлы (PIF, OV? и др. файлы)
- файлы текстовых процессоров поддерживающих макроcы (DOC, XLS и др.файлы)

С каждым днем этот список растет.

Чаще всего вирусы внедряются в файлы COM, EXE и DOC

ЗАГРУЗОЧНЫЕ

загрузояные вирусы распространяются в BOOT секторах дисков и дискет

- BR - на дискетах
- MBR - на жестком диске

При загрузке этих дискет выполняется программа в BOOT секторе этого диска, а следовательно и сам вирус. Плюс этого типа вирусов в том, что если прочитать этот инфицированный диск, то на нем не окажется ни одного файла.

ФАЙЛОВО-ЗАГРУЗОЧНЫЕ ВИРУСЫ

Вирусы данного типа обладают большей инфицирующей способностью, так как они распространяются в BOOT секторах диска и в файлах на этом диске.

СПОСОБЫ ЗАРАЖЕНИЯ СРЕДЫ ОБИТАНИЯ

Вирусы могут "имплантироваться" в следующие места файлов:

- конец файла
- начало файла
- середина файлов
- хвостовой части файлов (свободной)

Существует два основных типа загрузочных программ: EXE и COM. Рассмотрим требования к EXE-программам. DOS имеет четыре требования для инициализации ассемблерной EXE-программы: 1) указать ассемблеру, какие сегментные регистры должны соответствовать сегментам, 2) сохранить в стеке адрес, находящийся в регистре DS, когда программа начнет выполнение, 3) записать в стек нулевой адрес и 4) загрузить в регистр DS адрес сегмента данных.

Существуют определенные различия между программой, выполняемой как EXE-файл и программой, выполняемой как COM-файл.

1. Размер программы. EXE-программа может иметь любой размер, в то время как COM-файл ограничен размером одного сегмента и не превышает 64К. COM-файл всегда меньше, чем соответствующий EXE-файл; одна из причин этого - отсутствие в COM-файле 512-байтового начального блока EXE-файла.

2. Сегмент стека. В EXE-программе определяется сегмент стека, в то время как COM-программа генерирует стек автоматически. Таким образом при создании ассемблерной программы, которая будет преобразована в COM-файл, стек должен быть опущен.

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

4. Инициализация. EXE-программа записывает нулевое слово в стек и инициализирует регистр DS. Так как COM-программа не имеет ни стека, ни сегмента данных, то эти шаги отсутствуют. Когда COM-программа начинает работать, все сегментные регистры содержат адрес префикса программного сегмента (PSP),

- 256-байтового (шест. 100) блока, который резервируется операционной системой DOS непосредственно перед COM или EXE программой в памяти. Так как адресация начинается с шест. смещения 100 от начала PSP, то в программе после оператора SEGMENT кодируется директива ORG 100H.

Warning: No STACK Segment

(Предупреждение: Сегмент стека не определен)

ПРИМЕР ПРОГРАММЫ

Программа преобразования двузначного шестнадцатеричного числа в символьном виде в двоичное представление.

Выход: результат преобразования помещается в регистр dl.

<1> data segment para public “data” ;сегмент данных

<2> message db “Введите две 16-теричные цифры, $”

<4> stk segment stack

<5> db 256 dup (“?”) ;сегмент стека

<7> code segment para public “code” ;начало сегмента кода

<8> main proc ;начало процедуры main

<9> assume cs:code,ds:data,ss:stk

<10> mov ax,data ;адрес сегмента данных в регистр ах

<11> mov ds,ax ;ax в ds

<13> mov dx,offset message

<15> xor ax,ax ;очистить регистр ах

<16> mov ah,1h ;1h в регистр ah

<17> int 21h ;генерация прерывания с номером 21h

<18> mov dl,al ;содержимое регистра al в регистр dl

<19> sub dl,30h ;вычитание: (dl)=(dl)-30h

<20> cmp dl,9h ;сравнить (dl) с 9h

<21> jle M1 ;перейти на метку М1, если dl<9h или dl=9h

<22> sub dl,7h ;вычитание: (dl)=(dl)-7h

<23> M1: ;определение метки М1

<24> mov cl,4h ;пересылка 4h в регистр сl

<25> shl dl,cl ;сдвиг содержимого dl на 4 разряда влево

<26> int 21h ;вызов прерывания с номером 21h

<27> sub al,30h ;вычитание: (dl)=(dl)-30h

<28> cmp al,9h ;сравнить (al) c 9h

<29> jle M2 ;перейти на метку М2, если al<9h или al=9h

<30> sub al,7h ;вычитание: (al)=(al)-7h

<31> M2: ;определение метки М2

<32> add dl,al ;сложение: (dl)=(dl)+(al)

<33> mov ax,4c00h ;пересылка 4с00h в регистр ax

<34> int 21h ;вызов прерывания с номером 21h

<35> main endp ;конец процедуры main

<36> code ends ;конец сегмента кода

<37> end main ;конец программы с точкой входа main

Строки 4-6 описывают сегмент стека, который является просто областью памяти длиной 256 байт, инициализированной символами «”?”». Отличие сегмента стека от сегментов других типов состоит в использовании и адресации памяти. В отличие от сегмента данных (наличие которого необязательно, если программа не работает с данными), сегмент стека желательно определять всегда.




Строка 9 содержит директиву ассемблера, которая связывает сегментные регистры с именами сегментов.

Строки 10-11 выполняют инициализацию сегментного регистра DS.

Строка 15 подготавливает регистр АХ к работе, обнуляя его.

Строки 16-17 обращаются к средствам операционной системы для ввода символа с клавиатуры. Введенный символ операционная система помещает в регистр AL.

Строка 18 пересылает содержимое AL в регистр DL. Это делается для того, чтобы освободить AL для ввода второй цифры.

Строка 19 преобразует символьную цифру в ее двоичный эквивалент путем вычитания 30h, в результате чего в регистре DL будет двоичное значения числа.

В строках 20-21 выясняется, нужно ли корректировать двоичное значение DL. Если оно лежит в диапазоне 0…9, то в DL находится правильный двоичный эквивалент введенного символа шестнадцатеричной цифры. Если значение в DL больше 9, то введенная цифра является одним из символов A,B,C,D,E,F. В первом случае строка 21 передаст управление на метку М1.

В строках 24-25 значение в DL сдвигается на 4 разряда влево, освобождая место в младшей тетраде под младшую шестнадцатеричную цифру.

В строке 26 в регистр AL вводится вторая шестнадцатеричная цифра.

В строках 27-29 выясняется, попадает ли двоичный эквивалент второго символа шестнадцатеричной цифры в диапазон 0…9. Наша вторая цифра не попадает в диапазон, поэтому для получения правильного двоичного эквивалента нужно произвести дополнительную корректировку. Это делается в строке 38.

Строки 33-34 предназначены для завершения программы и возврата управления операционной системе.

СТРУКТУРЫ

Описание типа структуры

Структура - это составной объект, занимающий несколько соседних ячеек памяти. Это тип данных, состоящий из фиксированного числа элементов разного типа. Компоненты структуры называются полями, они могут быть разного типа (размера) - байт, слово и т. д. Поля именуются, доступ к полям осуществляется по именам. Для использования структур в программе необходимо выполнить 3 действия.

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

2. Определить экземпляр структуры. Этот этап подразумевает инициализацию конкретной переменной с заранее определенной структурой.

3. Организовать обращение к элементам структуры.

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

Описание шаблона структуры.

Прежде чем использовать структуру, надо описать ее тип - указать, сколько в ней полей, какие имена у полей и т. д. Описание типа структуры выглядит так:

Описание типа открывает директива STRUC, где указывается имя, которое дали типу структуры. Это же имя должно быть в директиве ENDS. Между этими двумя директивами может быть указано любое число директив, описывающих поля структуры.

Например, тип структуры DATE из трех полей Y (год), M(месяц), D(день) можно описать так:

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

После того как описан тип структуры, можно определять в программе переменные этого типа, отводить под них память. Такие переменные называются переменными-структурами или просто структурами. Описываются они с помощью директив следующего вида:

имя_переменной имя_типа <нач_знач >

Пример описания переменных-структур:

Это директивы особого рода. До этого мы рассматривали директивы, названиями которых были служебные слова, а здесь названием является имя DATE. Каждая такая директива описывает одну переменную, имя которой указывается в начале директивы.

DT2 DATE <2005, , > эквивалентно DT2 DATE <2005>

DT3 DATE < , , > эквивалентно DT3 DATE < >

Одной директивой можно описать сразу несколько структур, т. е. можно описать массив, элементами которого являются структуры. Например по директиве

DTS DATE < , 12, 5 > 10 dup (<>)

описывается массив из 11 структур типа DATE, причем поля первой из них будут иметь начальные значения: 2004, 12, 5, а остальные десять структур получают один и тот же набор начальных значений, взятых по умолчанию: 2004, 3, ?.

Описав тип структуры и переменные этого типа, получаем право работать с этими переменными-структурами. Как единое целое структуры обрабатываются редко, обычно они обрабатываются по полям. чтобы сослаться на поле структуры, надо использовать конструкцию вида

<имя переменной-структуры>.<имя поля>

Такая конструкция обозначает ту ячейку памяти, которую занимает указанное поле указанной переменной. Встречая эту конструкцию, ассемблер заменяет ее на адрес данной ячейки.

Пример. Если в переменной DT1 хранится мартовская дата, то требуется записать сюда дату следующего дня года.

jne FIN ; не март - FIN

je APRL ; 31 марта - APRL

inc DT1.D ; следующий день в марте

APRL: mov DT1.M, 4 ; замена 31 марта 1 апреля

ОБЪЕДИНЕНИЯ

Объединение - тип данных, позволяющий трактовать одну и ту же область памяти как данные, имеющие разные типы и имена. Описание объединений в программе напоминает описание структур, т. е. сначала указывается шаблон, в котором с помощью директив описания данных перечисляются имена и типы полей:

Отличие объединений от структур состоит в том, что при определении переменной типа объединения память выделяется в соответствии с размером максимального элемента. Обращение к элементам объединения происходит по их именам, но при этом нужно помнить, что все поля в объединении накладываются друг на друга. В качестве элементов объединения можно использовать и структуры.

Цель. Изучение структуры EXE- и COM-программы. Получение навыков вывода данных на экран монитора.

Задание. Разработать EXE-программу вывода символа на экран, и COM- программу вывода на экран строки.

Теоретические сведения

Структура программы

Исходный программный модуль состоит из команд и директив. Команды управляют работой процессора, а директивы указывают ассемблеру и редактору связей каким образом следует объединять, команды для создания модуля, который и станет работающей программой.

Команда на языке ассемблера состоит не более чем из четырех полей. Ниже приведен формат и пример команды с указанием названия его полей:

Метка Код операции Операнды ; Комментарий

MET: MOVE AX, BX ; Пересылка

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

Оператор директивы состоит из символического имени, кода псевдооперации, поля операндов и комментария. Структура директивы аналогична структуре команды. Второе поле – код псевдооперации определяет смысловое содержание директивы. Как и команды, у директивы есть операнды, причем их может быть один или несколько и они отделяются друг от друга запятыми. Допустимое число операндов в директиве определяется кодом псевдооперации. Например:

Директива может быть помечена символическим именем и содержать поле комментария. Символическое имя, стоящее в начале директивы распределения памяти, называется переменной. В отличие от метки команды после символического имени директивы двоеточие не ставиться.

Программа на языке ассемблера состоит из программных модулей, содержащихся в различных файлах. Каждый модуль, в свою очередь, состоит из операндов или директив ассемблера и заканчивается директивой END. Метка, стоящая после кода псевдооперации END, является точкой входа в программу.

Каждый модуль разбивается на отдельные части директивами сегментации, определяющими начало и конец сегмента. Любой сегмент начинается директивой начала сегмента – SEGMENT и заканчивается директивой конца сегмента – ENDS. В начале директив сегментации ставится имя сегмента.

Каждый сегмент может быть также разбит на части. В общем случае информационные сегменты SS, ES и DS состоят из определений данных, а программный сегмент CS – из команд и директив, группирующих команды в блоки.

Программный сегмент может разбиваться на части директивами определения процедур – некоторых выделенных блоков программы. Как и для определения сегмента, имеются две такие директивы – директива начала PROC и директива конца ENDP. Процедура имеет имя, которое должно включаться в обе директивы, процедуры в сегменте могут располагаться последовательно одна за другой, могут быть также вложенными одна в другую.

Принципиальной особенностью COM-программы является то, что в отличие от EXE-программы, которая содержит отдельные сегменты данных, стека и кода, COM-программ, в большинстве случаев, может содержать лишь один основной сегмент (сегмент кода), в котором размещаются и код, и данные, и стек. Кроме того, EXE-программа, в отличие от COM-программы, содержит так называемый EXE-заголовок (256 байт), при помощи которого загрузчик выполняет настройку ссылок на сегменты в загруженном модуле, а так как и COM- и EXE- программа должна загружаться с адреса PSP:0100h (100h=256), COM-программа должна содержать в начале сегмента кода директиву, позволяющую осуществить такую загрузку (ORG 100H).

Ниже приведены примеры, иллюстрирующие основные особенности структуры EXE- и COM-программ, написанных на языке ассемблера:

Пример. Структура EXE-программы:

;Определение сегмента стека

STAK SEGMENT STACK

;Определение сегмента данных




. . . ;Определение других переменных

;Определение сегмента кода

XOR AX,AX ;Точка входа в программу START

MOV BX, data ;и обязательная инициализация

MOV DS,BX ;регистра DS в начале программы

CALL PROC1 ;Пример вызова подпрограммы

MOV AH,4CH ;Операторы завершения программы

Пример. Структура COM-программы:

;Определение сегмента кода

ORG 100H ;Начало необходимое для COM-программы

INT 21H ;Операторы завершения программы

BUF DB 6 ;Определение переменной типа Byte

. . . ;Определение других переменных

Вывод на экран

Вывод информации в ассемблерных программах осуществляется обычно при помощи сервисных функций DOS (прерывание 21h) или BIOS (прерывание 10h). Процесс вывода состоит в следующем:

- определенные регистры микропроцессора загружаются выводимой информацией или адресом буфера, содержащего выводимую информацию;

- в регистр AH заносится номер используемой для операции вывода функции;

Ниже представлен перечень функций прерывания 21h и 10h, использующихся для вывода информации.

Прерывание 21h.

Функция 02h

Вывод на дисплей.

Описание. Посылает символ из DL на стандартный вывод. Обрабатывает символ Backspace (ASCII 8), перемещая курсор влево на одну позицию и оставляя его в новой позиции.

Функция 05h

Вывод на принтер.

DL= символ, записываемый на стандартный принтер

Функция 09h

DS:DX=адрес строки, заканчивающейся символом '$'.

Описание. Строка, исключая завершающий ее символ '$', посылается на стандартный вывод. Символы Backspace обрабатываются как в функции 02h. Обычно, чтобы перейти на новую строку, включают в текст пару CR/LF (ASCII 13H и ASCII 0aH). Строки, содержащие '$', можно выдать через 40h (BX=0), которая посылает символ в DL на стандартное устройство принтера, обычно LPT1.

Прерывание 10h.

Функция 02h

BH = видео страница

DH,DL = строка, колонка (считая от 0)

Описание. Устанавливает курсор в позицию DH,DL. Установка курсора на строку 25 делает курсор невидимым.

Функция 09h

Писать символ/атрибут в текущей позиции курсора.

BH = номер видео страницы

AL = записываемый символ

CX = счетчик (сколько экземпляров символа записать)

BL = видео атрибут (текст) или цвет (графика)

Описание. Выводит на экран в текущую позицию курсора символ с заданным атрибутом.

Функция 0ah

Писать символ в текущей позиции курсора.

BH = номер видео страницы

AL = записываемый символ

CX = счетчик (сколько экземпляров символа записать)

Описание. Выводит на экран в текущую позицию курсора заданный символ.

Функция 13h

ES:BP – выводимая строка

CX = длина строки (подсчитываются только символы)

DH,DL = позиция (строка, колонка) начала вывода

BH = номер страницы

AL = код подфункции:

0=атрибут в BL; курсор без изменения

1=атрибут в BL; курсор – в конец строки

2=формат строки: char,attr. ; курсор без изменения

3=формат строки: char,attr. ; курсор – в конец строки

Описание. Выдает строку в позиции курсора. Символы 0dH (CarRet), 0aH (LineFeed), 08H (backspace) и 07H (Beep) трактуются как команды управления и не высвечиваются.

Некоторые функции прерывания 10h используют для вывода атрибут символа. Для адаптеров цветной графики в текстовом режиме атрибут определен следующим образом:

fgB background brt foreground

foreground – цвет переднего плана (от 0 до 0fH);

brt – интенсивность: 1=передний план яркий;

background – фоновый цвет (от 0 до 7);

fgB – мерцание: 1=передний план мерцает;

Видеоадаптер поддерживает следующие цвета:

00H черный 01H синий 02H зеленый 03H голубой 04H красный 05H розовый 06H коричневый 07H серый 08H темно-серый 09H ярко-синий 0aH светло-зеленый 0bH светло-голубой 0cH светло-красный 0dH светло-розовый 0eH желтый 0fH белый

Вычислить значение атрибута можно, используя следующее выражение:

(фон * 16) + передний план + (128 для мерцания)

Приведенный ниже фрагмент программы иллюстрирует процесс вывода строки на экран.

MOV AH,09H ;Выбор функции прерывания

MOV DX,OFFSET STR ;Занесение в DX адреса выводимой строки

STR DB 10,13,'Hello$'

Лабораторная работа №2

Циклы. Ввод с клавиатуры

Цель. Получение навыков организации циклических структур в ассемблерных программах. Ввод символов с клавиатуры.

Задание. Разработать программу, ввода строковых данных с клавиатуры. Произвести обработку введенных строк в соответствии с вариантом и вывести результат на экран.

Читайте также: