Поиск по базе сайта:
II. Реальный режим работы процессоров. Язык ассемблера icon

II. Реальный режим работы процессоров. Язык ассемблера




НазваII. Реальный режим работы процессоров. Язык ассемблера
Сторінка1/3
Дата конвертації16.07.2013
Розмір0.52 Mb.
ТипДокументи
  1   2   3

II. Реальный режим работы процессоров. Язык ассемблера


II.Реальный режим работы процессоров. Язык ассемблера



3.Среда выполнения программ в реальном режиме

После рестарта процессор находится в реальном режиме. Именно в реальном режиме функционирует базовая система ввода/вывода, загрузчики операционных систем, а также и некоторые операционные системы, например MS DOS.

3.1.Управление памятью

В реальном режиме адрес имеет размер 20 бит, и, следовательно, максимальный объем адресуемой памяти составляет 1 Мб. Для формирования 20 битового адреса в памяти используются два 16 битовых регистра: сегментный регистр и регистр смещения. Сегментный регистр определяет базовый адрес сегмента. В нем содержатся старшие 16 бит базового адреса сегмента, младшие четыре бита предполагаются равными 0. В регистре смещения находится смещение внутри сегмента (относительно базового адреса сегмента). Смещение может также задаваться непосредственной константой. Смещение добавляется к базовому адресу сегмента и таким образом получается 20 битовый адрес в памяти. Более просто можно описать вычисление следующим образом – 16-ти битовое значение сегментного регистра сдвигается на 4-ре бита влево и к нему добавляется значение смещения, в результате получается 20-ти битовое значение (см. рис.3.1). Именно такая схема применялась в 8086 и 8088 процессорах.

Начиная с 80286 процессора, как уже говорилось в предыдущих лекциях, для описания сегментов применяются теневые регистры (невидимая часть сегментных регистров). В них содержится адрес и предел (размер) сегмента. В реальном режиме предел всегда равен 64 Кб, а адрес сегмента вычисляется во время изменения видимой части сегментного регистра путем сдвига ее на 4-ре бита влево. Следует заменить, что, начиная с 80386 процессора, смещение может превышать 64 Кб за счет использования 32-х битовых методов адресации. Если смещение будет превышать предел, то произойдет исключение основной защиты.

3.2.Прерывания и исключения процессора

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

Исключение – это прерывание, инициируемое самим процессоров в ходе каких-либо внутренних ошибок (например, ошибка деления).

Для того чтобы изменить ход выполнения последовательности кодов в реальном режиме, необходимо изменить содержимое сразу двух регистров: регистра сегмента кода (CS) и указателя команды (IP). Значение, помещаемое в эти регистры, называется вектором прерывания.

В процессорах семейства Intel предусмотрено 256 прерываний и соответственно 256 векторов прерываний. Все вектора прерываний объединяются в таблицу, состоящую из 256 4-х байтовых элементов и занимающую 1 Кб. В реальном режиме эта таблица находится в самом начале памяти по адресу 0:0 или (просто по 0-му физическому адресу).

Каждый элемент таблицы состоит из двух полей. Первые два байта представляют собой значение, заносимое в регистр IP, последние два байта содержат значение, заносимое в регистр CS.

Всего существует четыре вида прерываний: исключения, немаскируемое прерывание, маскируемые аппаратные прерывания и пользовательские прерывания. Исключения генерируются процессором. Аппаратные прерывания генерируются аппаратурой (клавиатуры, таймер). Пользовательские прерывания генерируются с помощью команды INT. Полный список прерываний и исключений реального режима приводится в табл. 3.1.


Табл. 3.1. Вектора прерывания реального режима

Номер прерывания

Описание

0h

Деление на 0 или переполнение операнда назначения




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

При возникновении прерывания процессор выполняет следующие действия.

  1. Помещает в стек значение регистра IP

  2. Помещает в стек значение регистра CS

  3. Помещает в стек значение регистра FLAGS

  4. Загружает из таблицы векторов прерываний в соответствии с номером прерывания регистры IP и CS

  5. Запрещает аппаратные прерывания

При выходе из прерывания процессор выполняет следующие действия.

  1. Загружает из стека регистр FLAGS

  2. Загружает из стека регистр CS

  3. Загружает из стека регистр IP

3.3.Взаимодействие с базовой системой ввода/вывода

В реальном режиме операционной системе и программам пользователя доступны функции базовой системы ввода/вывода, находящейся в ПЗУ. Вызов функций осуществляется посредством вызова прерываний. Для базовой системы ввода/вывода отводятся прерывания в диапазоне 10h-1Fh. Все необходимые данные помещаются в регистры общего назначения, затем происходит вызов функции по команде int n. После выполнения функции, возвращаемые данные находятся в регистрах или памяти.

В данной главе рассматриваются только три основных сервиса.

3.3.1.Видео сервис

Функции видео сервиса вызываются через 10h прерывание. Далее приводится описание некоторых функций. Полное описание функций приводится в [5].

Установка видео режима

AH=0h; AL=видео режим (см табл.3.1)

Табл.3.1.Видео режимы и их характеристики

AL

Тип

Формат

Ячейка

Цвета

Адаптер

Адрес

0

Текст

40x25

8x8*

16/8

CGA, EGA

B800



8, 9, 0Ah

Режимы PCjr


0Dh

Графика

320x200

8x8

16

EGA, VGA

A000



13h

Графика

320x200

8x16

256

VGA

A000

* Размер ячейки зависит от типа видео адаптера

Установка позиции курсора

AH=2h; BH=видео страница; DH, DL = строка, колонка

^ Выбор текущей видео страницы

AH=5h; AL= номер страницы

Чтение символа/атрибута из текущей позиции курсора

AH=8h; BH=видео страница;

Возвращает: AL=код символа, AH=атрибут

^ Запись символа/атрибута в текущую позицию курсора

AH=9h; BH=видео страницы; AL=код символа; CX=число символов; BL=атрибут

Запись графической точки

AH=0Dh; BH=видео страница; DX,CX=строка, колонка; AL=цвет

Чтение графической точки

AH=0Dh; BH=видео страница; DX,CX=строка, колонка

Возвращает: AL=цвет

Запись символа в режиме телетайпа

AH=0Eh; AL=код символа; BL=цвет (для графических режимов)

3.3.2.Дисковый ввод/вывод

Функции дискового сервиса вызываются через 13h прерывание. Далее приводится описание некоторых функций. Полное описание функций приводится в [5].

Сброс устройства.

AH=0; DL=устройство (0,1,2 … -дисководы, 80h, 81h, 82h … жесткие диски).

^ Получение статуса ошибки после последней операции.

AH=1; DL=устройство;

Возвращает: AL=код ошибки

Чтение секторов.

AH=2; DL=устройство; CH+два старших бита CL=номер цилиндра; CL=номер сектора; AL=число секторов; ES:BX=>адрес буфера

Возвращает: cf=0 – нет ошибки; cf=1 – ошибка, AL=код ошибки

^ Запись секторов.

AH=3; DL=устройство; CH+два старших бита CL=номер цилиндра; CL=номер сектора; AL=число секторов; ES:BX=>адрес буфера

Возвращает: cf=0 – нет ошибки; cf=1 – ошибка, AL=код ошибки

Проверка секторов

AH=4; DL=устройство; CH+два старших бита CL=номер цилиндра; CL=номер сектора; AL=число секторов; ES:BX=>адрес буфера

Возвращает: cf=0 – нет ошибки; cf=1 – ошибка, AL=код ошибки

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

Функции сервиса клавиатуры вызываются через 16h прерывание. Далее приводится описание некоторых функций. Полное описание функций приводится в [5].

Чтение символа из буфера клавиатуры (ожидание, если символа нет)

AH=0;

Возвращает: AL=код символа; AH=код сканирования

^ Проверка наличия символа в буфере клавиатуры

AH=1;

Возвращает: zf=1 – символа нет; zf=0 – символ есть, AL=код символа; AH=код сканирования

Чтение состояния переключающих клавиш

AH=2;

Возвращает: AL=биты статуса


+-7--6--5--4--3--2--1--0+ Выполняет INT 16H Fn 02H

¦I ¦C ¦N ¦S ¦a ¦c ¦sL¦sR¦ AL=байт по 0:0417

+-----------------------+ bit

¦ ¦ ¦ ¦ ¦ ¦ ¦ +-_ 0: shift (правая сторона) (AL & 01H)

¦ ¦ ¦ ¦ ¦ ¦ +----_ 1: shift (левая сторона) (AL & 02H)

¦ ¦ ¦ ¦ ¦ +-------_ 2: Ctrl (любая сторона) (AL & 04H)

¦ ¦ ¦ ¦ +----------_ 3: Alt (любая сторона) (AL & 08H)

¦ ¦ ¦ +-------------_ 4: ScrollLock состояние (AL & 10H)

¦ ¦ +----------------_ 5: NumLock состояние (AL & 20H)

¦ +-------------------_ 6: CapsLock состояние (AL & 40H)

+----------------------_ 7: Insert состояние (AL & 80H)

Поместить символ в буфер клавиатуры

AH=5; CL=код символа; CH=код сканирования

Возвращает: AL=статус: 0=успешное завершение, 1=буфер полон.

^ 4.Объектные и запускаемые модули. Операционная система

4.1.Создание запускаемых модулей

Написанные программы на каком-либо языке не могут быть выполнены непосредственно (машинный код не является языком программирования). Необходимо подвергнуть исходный код некоторым преобразованиям, после чего его можно будет запустить. Существует два вида преобразования: интерпретация и компиляция.

Интерпретация очень проста в реализации: пошагово для каждой конструкции происходит поиск и запуск соответствующей подпрограммы. Даже если конструкция встречается сотни раз, каждый раз к ней будет применяться распознавание. Более того, для каждой программы необходимо хранить все возможные подпрограммы, так как не возможно предугадать, понадобятся они или нет. Классическим интерпретатором является БЕЙСИК.

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

В современных языках программирования (как высокого уровня, так и низкого) построенных с использованием компиляции используется следующие два этапа для получения запускаемого модуля:

  • Преобразование исходного текста в машинный код (компиляция) и получение объектных модулей. Хотя и в объектных модулях и находится машинный код, он еще не готов для выполнения, так как очень редко в объектных модулях содержится вся программа. Обычно программа располагается в нескольких модулях, которые могут быть скомпилированы отдельно. В объектных модулях содержатся внешние ссылки на другие модули (например, некоторая процедура может вызывать процедуру, которая находится в другом модуле).

  • На втором этапе редактор связей объединяет все объектные модули в один запускаемый модуль и разрешает все внешние ссылки. Если остается хотя бы одна неразрешенная ссылка, запускаемый модуль не может быть создан.

Такой двухэтапный подход позволяет значительно ускорить процесс создания запускаемого модуля (нет необходимости каждый раз компилировать всю программу целиком) и производить компиляцию при малом объеме оперативной памяти.

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

4.2.Операционная система и ее назначение

Сама по себе программа мало полезна, так как она сама не может загрузиться в память и тем более управлять ресурсы компьютера. Необходима некоторая служебная программа, которая будет загружать программы пользователя в память, подготавливать ее к выполнению (провязывать по загружаемым адресам – корректирование ссылок в программе в соответствие с адресом, по которому программа была загружена) и выполнять ее запросы. Такая программа называется операционной системой.

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

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



^ 5. Ассемблер Intel 80х86

5.1.Назначение языка ассемблера

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

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

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

5.2.Основные языковые конструкции и директивы

Ассемблер, как и все другие языки программирования, имеет свой синтаксис. Далее рассматривается основные языковые конструкции.

5.2.1.Общий синтаксис

Синтаксис языка ассемблера довольно прост. Каждая команда записывается на отдельной строке. Строка разделяется на три поля:

  • Метки. Если после метки идет команда процессора, то стразу же после метки необходимо поставить ":". Если после метки идет директива компилятору, то ":" ставить не нужно.

  • Собственно команда с операндами или директива компилятору с операндами.

  • Комментарий. Комментарию обязательно должен предшествовать символ ";".

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

^ MyLabel: mov eax,ebx ; занесение значения из регистра ebx в регистр eax.

; просто комментарий

MyLabel1: ; просто метка

Mov eax,ebx

MyProcedure proc ; пример директивы компилятору

End ; конец модуля

5.2.2.Определние сегментов и групп сегментов

Программа на языке ассемблера состоит из процедур и переменных. Однако в архитектуре Intel процедуры не могут находиться просто в памяти, они должны принадлежать некоторым сегментам. Сегменты также формируются в программе. Для описания сегментов используются директивы segment и ends :

^ Имя_сегмента segment [<выравнивание>] [<объединение>] [<режим адресации>] [<‘класс’>]

; Все, что находится между этими директивами, находится внутри соответствующего сегмента.

^ Имя_сегмента ends

  • [<выравнивание>]. Выравнивание сегмента: byte (1 байт), word (2 байта), para (16 байт, используется по умолчанию), dword (4 байта) или page (4096 байт). Используется для выравнивания структур в памяти для повышения производительности.

  • [<объединение>]. Объединение сегментов: public (сегменты добавляются друг к другу и составляют один сегмент), stack (объединение сегментов стека), common (наложение сегментов), at (расположение сегмента по физическому адресу).

  • [<режим адресации>]. Определяет текущий режим адресации сегмента: USE16 (16 битовые операнды адреса и данных), USE32 (32 битовые операнды адреса и данных).

  • [<‘класс’>]. В апострофах может указываться также имя класса сегмента. Сегменты с одинаковыми классами будут располагаться рядом, а при совпадении имен объединяться вместе.

Пример сегмента стека:

^ MyStackSeg Segment public para stack ‘stack’

Dd 1000 dup (?)

MyStackSeg ends

Сегменты могут объединяться в группы для адресации одним сегментным регистром. Для объединения сегментов используется следующая директива:

^ Имя_группы Group имя_сегмента, имя_сегмента, …


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


^ CodeSeg segment



Assume cs:CodeSeg, ds:Data1Seg, ss:StackSeg, es:nothing, fs:DataGr

Mov ax,Data1Seg

Mov ds,ax



; а с этого места будет другое использование сегментов

Assume ds:Data2Seg, es: Data1Seg, gs:DataGr

Mov cx,ds

Mov es,cx

Mov bx, Data2Seg

Mov ds,bx



CodeSeg ends


DataGr Group Data1Seg, Data2Seg


Data1Seg segment



Data1Seg ends


Data2Seg segment



Data2Seg ends


StackSeg segment stack ‘Stack’

Dd 1000 dup (?)

StackSeg ends

end

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

Mov ax,SegmentName

Mov ds,ax

5.2.3.Определение процедур

Допустимо размещать команды процессора непосредственно в сегменте, однако лучше их размещать в процедурах. Для описания процедуры используются директивы proc и endp. После директивы proc могут находиться два параметра: far и near (принимается по умолчанию). Far показывает то, что вызов этой процедуры осуществляется по дальнему адресу, т.е. сегмент:смещение. Near показывает, что вызов этой процедуры осуществляется по ближнему адресу, т.е. по смещению. Дальние процедуры доступны из любых сегментов. Ближние процедуры доступны только из сегмента, в котором они находятся.

  1   2   3



Схожі:




База даних захищена авторським правом ©lib.exdat.com
При копіюванні матеріалу обов'язкове зазначення активного посилання відкритою для індексації.
звернутися до адміністрації