Файл: Системное программирование.doc

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 06.02.2025

Просмотров: 9118

Скачиваний: 4

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

СОДЕРЖАНИЕ

Системное программирование

Контрольные вопросы

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 Кафедра Вычислительной Техники и Программирования Московского Государственного Открытого Университета

В качестве сегментных регистров можно использовать регистры CS, DS, SS и ES. Начальные адреса сегментов памяти можно хранить и в других регистрах, однако использовать их для сегментирования адресов не удастся.

На начальные адреса сегментов накладываются ограничения. В связи с тем, что абсолютные адреса 20-разрядные, а сегментные регистры 16-разрядные, адрес сегмента должен быть кратен 16 (последние 4 бита нулевые, что в шестнадцатеричной форме имеет вид xxxx0h). В результате в сегментных регистрах хранятся первые 16 битов начального адреса сегмента (рис. 16).

Рис. 16. Схема формирования физического адреса.

Например, если адресом начала сегмента является число 12340h, то в сегментном регистре будет храниться величина 1234h. Процессор учитывает такую особенность и при сегментировании адреса к содержимому сегментного регистра добавляет справа 0 и затем прибавляет смещение, указанное в команде. Поскольку добавление справа нуля к шестнадцатеричному числу эквивален­тно умножению числа на 16, то формула вычисления абсолютного адреса по адресной паре CS:disp имеет вид:

При записи ко­манд на ассемблере конструкция вида:

<сегментный регистр>:<адресное выражение>

называется адресной парой(илилогическим адресом) и указывает, что адрес, являю­щийся значением выражения, должен быть просегментирован по указанному ре­гистру.

Логический адрес может находиться в пределах:

0000h:0000h <= [логический адрес] <= FFFFh:000Fh

На рис. 17 изображено все доступное адресное пространство оперативной памяти. Показан некоторый сегмент (он может относиться к сегменту кода, данных, стека или к дополнительному сегменту), расположенный по адресу 0010h. В самом сегменте указан адрес с помощью смещения 0120h. Таким образом, логический адрес 0010h:0120h соответствует физическому адресу 00120h.

Рис. 17. Соответствие физического адреса логическому.

Запись вида CS:, DS:, SS: и ES: принято называть префиксом сегментного регистра. Префикс указывается перед адресом, который должен быть просегментирован. С помощью префикса замены сегмента можно обратиться к операнду с использованием любого из четырёх сегментных регистров. Функциональное распределение сегментных регистров следующее (рис. 18).


Ре­гистр CS всегда должен указывать на начало сегмента команд. Адрес очередной подлежащей выполнению команды, указы­вается регистровой парой CS:IP. Указатель команд IP содержит смещение команды, отсчитанное от начала сегмента команд. Регистр DS должен указывать на начало сегмен­та данных, а SS – на начало сегмента стека. Регистр ES (а также позднее введенные FS и GS) может указывать на любой сегмент памяти. Например, инструкция MOV AX, [BP] загружает в регистр AX содержимое слова памяти по адресу SS:BP, однако, инструкция MOV AX, ES:[BP] загрузит содержимое слова по адресу ES:BP.

Рис. 18. Распределение памяти с помощью сегментных регистров.

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

Табл. 5. Сегментные префиксы.

Код

Префикс

Описание

26

ES:

Использование сегмента ES.

2E

CS:

Использование сегмента CS.

36

SS:

Использование сегмента SS.

3E

DS:

Использование сегмента DS.

Приведем примеры явного указания сегментных регистров. Предположим, требуется записать в регистр АХ содержимое ячейки памяти M, расположенной в сегменте команд. Использовать команду MOV AX,M нельзя, поскольку она воспримется как MOV AX, DS:M и потому запишет в АХ содержимое ячейки, имеющей смещение M, но находящейся в сегменте данных. Поэтому следует явно указать сегментный регистр, т.е. записать команду MOV AX, CS:M.

Другой типичный случай – требуется работать с сегментом памяти, отличным от сегментов команд, данных и стека. В этом случае на начало сегмента уста­навливается регистр ES и при ссылках на ячейки сегмента используется этот регистр, например: MOV AX, ES:M. Опускать префикс ES: нельзя, т.к. он не подразумевается по умолчанию.


4.2. Директивы сегментации

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

<имя сегмента> SEGMENT <параметры>

<предложение>

...

<предложение>

<имя сегмент> ENDS

Между директивами может быть указано лю­бое число предложений, которые ассемблер разместит в одном сегменте памяти. Раз­мер сегмента не должен превышать 64 Кб. В программе может быть несколько сегментов с одним и тем же именем. В этом случае они рассматриваются как один сегмент, разделенный на несколько частей, и все предложения из этих сегментов ассемблер объединит вместе.

Ассемблер размещает в памяти программные сегменты последовательно, с адреса, кратного 16 (выравнивание по границе параграфа), и имени каждого сегмента присваивает его номер в памяти, т.е. первые 16 разрядов начального адреса данного сегмента.

Приведем пример использования директивы SEGMENT:

A SEGMENT

A1 DB 100h DUP(?)

A2 DW 8

A ENDS

В SEGMENT

B1 DW A2

B2 DD А2

В ENDS

С SEGMENT

L: MOV AX, A2

MOVBX,B2

С ENDS

При трансляции предложений ассемблер ставит в соответствие опи­санным именам переменных и меткам адреса – смещения соответствующих ячеек памяти, отсчитанные от начала сегмента. В примере имя A1 получит сме­щение 0, имя A2 – смещение 100h, имя B1 – смещение 0, имя B2 – смещение 2, имя L – смещение 0. Имена переменных и метки рассматриваются как адресные выражения. Но есть возможность рассматривать их и как кон­стантные, для чего используется оператор:

OFFSET <имя>

Значением оператора является смещение переменной, относительно начала сегмента, в котором оно описано:

OFFSET A1 = 0

OFFSET A2 = 100h

OFFSET L = 0

Оператор SEG позволяет узнать, в каком сегменте описа­но имя переменной или метка:

SEG <имя>

Значением оператора является имя сегмента, в котором описана переменная-операнд:

SEG A1 = SEG A2 = А

SEG B1 = SEG B2 = В

SEG L = С

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

Директиву ASSUME обычно указывают в начале сегмента команд:

ASSUME <пара> {, <пара>}


где <пара> обозначает адресную пару <сегментный регистр>:<имя сегмента>

Например, директива:

ASSUME ES: A, DS: B, CS: C

сообщает транслятору, что для сегментирования адресов из сегмента A выбран регистр ES, для адресов из сегмента B – регистр DS, а для адресов из сегмента C – регистр CS.

Например, команда MOV AX, A2 будет транслироваться как MOV AX, ES:A2 (имя A2 описано в сегменте А), а команда MOV АХ, B2 как MOV AX, DS:B2 (имя B2 описано в сегменте B).

Перечисли особенности применения директивы ASSUME. Если в директиве ASSUME указано несколько пар с одним сегментным регистром, то последнее объявление отменяет предыдущее, т.к. каждому сегментному регистру можно поставить в соответствие только один сегмент. Например, по директиве:

ASSUME DS:A, DS:B

ассемблер будет считать, что регистр DS указывает только на сегмент В.

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

ASSUME ES:A, DS:A

на сегмент A будут указывать регистры ES и DS. Ассемблер выберет префикс, который в транслируемой команде подразумевается по умолчанию, поскольку его можно опустить и сэкономить память.

Если в директиве ASSUME в качестве второго элемента пары задано служеб­ное слово NOTHING (ничего), например ASSUME ES:NOTHING, то сегментный регистр не указывает ни на какой сегмент, и ассемблер не должен использовать регистр при трансляции команд. Для отмены ранее установленных соответствий для всех сегментных регистров, используется конструкция:

ASSUME NOTHING

Директива ASSUME может быть указана любое число раз. При этом несколько подряд идущих директив можно объединить в одну. Например, последовательность директив:

ASSUME ES:A ASSUME DS:B ASSUME CS:C

эквивалентна директиве:

ASSUMEES:A,DS:B,CS:C

Следует заметить, что директива ASSUME не загружает в сегментные ре­гистры начальные адреса сегментов. Поэтому выполне­ние программы должно начинаться с загрузки в сегментные регистры начальных адресов соответствующих сегментов памяти.

Например, сегментный регистр DS требуется установить на начало сегмента B, т.е. выполнить присваивание DS:=B. Команда пересылки MOV DS, B недопустима, т.к. имя сегмента есть константное выражение, а помещение непосредственного операнда в сегментный регистр запрещена. Поэтому инициализацию регистра DS можно выполнить, используя только несегментный регистр, например АХ:

MOV AX, B

MOV DS, AX

Аналогично загружаются регистр ES. Регистр CS загружать не нужно, т.к. к началу выполнения программы регистр уже будет указывать на начало сегмента команд. Такую загрузку выполнит операционная система, прежде чем передаст управ­ление программе.