- •Системное программирование
- •Контрольные вопросы
- •2. Программная модель микропроцессора 8086
- •2.1. Представление информации
- •2.2. Регистры микропроцессора
- •2.3. Формат машинной команды
- •2.4. Способы задания операндов команды
- •Контрольные вопросы
- •3. Основные понятия языка ассемблера
- •3.1. Предложения
- •3.2. Директивы определения данных
- •3.3. Выражения
- •Контрольные вопросы
- •4. Сегментированная модель памяти
- •4.1. Сегментирование адресов
- •4.2. Директивы сегментации
- •4.3. Общая структура программы
- •4.4. Модели памяти
- •Контрольные вопросы
- •5. Основные группы команд
- •5.1. Соглашению по описанию команд
- •5.2. Команды пересылки данных
- •5.3. Арифметические команды
- •5.4. Логические команды
- •5.5. Команды переходов
- •5.6. Команды организации циклов
- •5.7. Команды обработки строк
- •5.8. Стековые команды
- •5.9. Команды ввода-вывода
- •5.10. Команды прерываний
- •5.11. Команды управления микропроцессором
- •Контрольные вопросы
- •6. Подпрограммы
- •Контрольные вопросы
- •7. Разработка одномодульной программы
- •7.1. Трансляция и компоновка программы
- •7.2. Отладка программы
- •Контрольные вопросы
- •8. Разработка многомодульных программ
- •8.1. Принципы разработки модулей
- •8.2. Расширенное применение директивы сегментации
- •9. Упражнения
- •Контрольные вопросы
- •Программирование микропроцессорных устройств
- •10. Программирование системного таймера
- •10.1. Описание таймера-счетчика 8254
- •10.2. Режимы работы таймера
- •10.3. Структура регистров таймера
- •10.4. Упражнения
- •Контрольные вопросы
- •11. Программирование контроллера прерываний
- •11.1. Механизм обработки прерываний
- •11.2. Типы прерываний
- •11.3. Приоритеты прерываний
- •11.4. Контроллер прерываний 8259
- •11.5. Идентификация прерываний
- •11.6. Прерывания bios и ms-dos
- •11.7. Упражнения
- •Контрольные вопросы
- •12. Программирование параллельного порта
- •12.1. Интерфейс Centronics
- •12.2. Работа с параллельным портом на низком уровне
- •12.3. Стандартные средства работы с параллельным портом
- •12.4. Упражнения
- •Контрольные вопросы
- •13. Программирование последовательного порта
- •13.1. Основы последовательной передачи данных
- •13.2. Последовательный интерфейс rs-232c
- •13.3. Универсальный асинхронный приемо-передатчик 8250
- •13.4. Порты асинхронного адаптера
- •13.5. Стандартные средства программирования последовательного порта
- •13.6. Упражнения
- •Контрольные вопросы
- •Литература
- •141 Кафедра Вычислительной Техники и Программирования Московского Государственного Открытого Университета
4.3. Общая структура программы
Для небольших программ с одним сегментом кода, данных и стека типичной является следующая структура:
STACKSG SEGMENT STACK ; сегмент стека
DB 128 DUP(?)
STACKSG ENDS
DATASG SEGMENT ; сегмент данных
<описания переменных>
DATASGENDS
CODESGSEGMENT; сегмент команд
ASSUME CS: CODESG, DS: DATASG, SS: STACKSG
S: MOV AX, DATASG
MOV DS, AX ; загрузить DS
... ; остальные команды
MOVAX, 4C00h ; завершить программу с кодом возврата 0 INT 21h ; выполнить прерывание 21h
CODESG ENDS
END S ; конец программы, точка входа
Сегмент стека описан с параметром STACK, поэтому в самой программе не нужно загружать сегментный регистр SS. Сегмент стека следует описывать всегда, даже когда не предполагается его использовать, т.к. стек использует операционная система для обработки прерываний. Рекомендуемый размер сегмента стека с запасом составляет 128 байтов. Если программа сама использует стек, то под него отводится столько места, сколько требуется, плюс 128 байтов.
Затем следует сегмент данных, в котором необходимо описать все используемые переменные с помощью директив описания данных. В сегменте кода первой директивой должна идти ASSUME, для задания соответствия между сегментами и соответствующими сегментными регистрами. После директивы ASSUME выполняется инициализация сегментного регистра данных. Затем могут идти все остальные команды программы.
Обязательным последним действием программы в сегменте кода должен быть вызов специальной функции под номером 4C. Функция определена за прерыванием 21h и предназначена для выполнения корректного выхода в операционную систему MS-DOS после завершения работы программы. Для выполнения функции в регистр AH должен быть помещен код 4Ch, а в регистр AL – код выхода. Как правило, успешное завершение программы соответствует коду выхода 0.
В конце программы следует указать директиву END – признак конца программы. Все строки после этой директивы игнорируются. В директиве указывается метка команды, с которой должно начаться выполнение программы (точка входа, в нашем примере эта метка S).
Все предложения должны входить в состав программного сегмента. Размещать их вне сегментов недопустимо. Вне сегментов разрешено указывать только директивы информационного характера (например, EQU). В сегменте данных разрешается размещать команды, а в сегменте команд описания переменных.
4.4. Модели памяти
Для программ, содержащих по одному сегменту кода, данных и стека, описание директив сегментации можно упростить. Для этого в транслятор TASM введена возможность использования упрощенных директив сегментации (табл. 6).
Табл. 6. Упрощенные директивы определения сегмента.
Режим MASM |
Режим IDEAL |
Назначение |
.CODE [имя] |
CODESEG [имя] |
Начало или продолжение сегмента кода. |
.DATA |
DATASEG |
Начало или продолжение сегмента инициализированных данных. Также используется для определения данных типа NEAR. |
.CONST |
CONST |
Начало или продолжение сегмента констант модуля |
.DATA? |
UDATASEG |
Начало или продолжение сегмента неинициализированных данных. Также используется для определения данных типа NEAR. |
.STACK [размер] |
STACK [размер] |
Начало или продолжение сегмента стека модуля. Параметр [размер] задает размер стека. |
.FARDATA [имя] |
FARDATA [имя] |
Начало или продолжение сегмента инициализированных данных типа FAR. |
.FARDATA? [имя] |
UFARDATA [имя] |
Начало или продолжение сегмента неинициализированных данных типа FAR. |
Совместно с упрощенными директивами сегментации используется директива модели памятиMODEL, которая позволяет управлять размещением сегментов и выполняет функции директивы ASSUME. Директива связывает сегменты с сегментными регистрами (но явно инициализироватьDSвсе равно необходимо). Формат директивы следующий:
MODEL <модель памяти>,[<модификатор директивы>],[<язык>],[<модификатор языка>]
Параметр "модель памяти"является обязательным. Он определяет модель сегментации памяти: набор и размеры сегментов данных и кода, способ связывания сегментов и сегментных регистров. В табл. 7 приведены возможные значения параметра.
Табл. 7. Модели памяти.
Модель |
Тип кода |
Тип данных |
Описание модели |
TINY |
NEAR |
NEAR |
Код и данные объединены в одну группу с именем DGROUP. |
SMALL |
NEAR |
NEAR |
Код занимает один сегмент, данные объединены в одну группу с именем DGROUP. Модель обычно используют для большинства программ на ассемблере. |
MEDIUM |
FAR |
NEAR |
Код занимает несколько сегментов, по одному на каждый объединяемый модуль. Все ссылки на передачу управления типа FAR. Данные объединены в одной группе; все ссылки на них типаNEAR. |
COMPACT |
NEAR |
FAR |
Код в одном сегменте; ссылка на данные типа FAR |
LARGE |
FAR |
FAR |
Код и данные расположены в нескольких сегментах. |
Параметр "модификатор директивы"уточняет особенности выбранной модели (табл. 8). Для микропроцессоров 386 и выше сегменты могут быть 16 или 32-разрядными. Приuse16 используется 16-разрядная адресация, а приuse32 – 32-разрядная. В первом случае размер сегмента не должен превышать 64 Кбайт, во втором – 4 Гбайт.
Табл. 8. Модификаторы модели памяти.
Модификатор |
Назначение |
USE16 |
Сегменты выбранной модели 16-разрядные. |
USE32 |
Сегменты выбранной модели 32-разрядные. |
DOS |
Программа будет работать в MS-DOS. |
Параметры "язык" и "модификатор языка"необязательные и задают особенности вызова процедур при связывании программ на различных языках программирования. При использовании директивы MODEL транслятор делает доступными несколько идентификаторов, к которым можно обращаться, чтобы получить информацию о параметрах модели (табл. 9).
Табл. 9. Идентификаторы, создаваемые директивой MODEL.
Идентификатор |
Значение переменной |
@CODE |
Физический адрес сегмента кода. |
@DATA |
Физический адрес сегмента данных типа NEAR. |
@FARDATA |
Физический адрес сегмента данных типа FAR. |
@FARDATA? |
Физический адрес сегмента неинициализированных данных типа FAR. |
@CURSEG |
Физический адрес сегмента неинициализированных данных типа NEAR. |
@STACK |
Физический адрес сегмента стека. |
Приведем пример использования упрощенных директив сегментации.
MASM; режим работыMASM
MODELSMALL; модель памятиSMALL
.DATA; начало сегмента данных
... ; определение данных
.STACK; начало сегмента стека
DB128DUP(?) ; размер стека 128 байт
.CODE; начало сегмента кода
S:MOVAX, @DATA; получить адреса сегмента данных
MOVDS,AX; адрес сегмента данных в регистрAX
... ; остальные команды программы
MOVAX, 4C00h ; завершить программу с кодом возврата 0 INT 21h ; выполнить прерывание 21h
ENDS ; конец программы, точка входа
Следует заметить, что стандартные и упрощенные директивы сегментации не исключают друг друга. Стандартные директивы необходимы для получения полного контроля над размещением сегментов в памяти и их комбинированием с сегментами других модулей (см. раздел 8.2). Упрощенные директивы удобно использовать для простых программ.