Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Глава 3. Как работает IBM/PC

ГЛАВА 3. КАК РАБОТАЕТ IBM/PC

[ Оглавление ]
     В  этой  главе  мы  рассмотрим  работу  "мозга" IBM/PC -
микропроцессора  8088  -   как   он   выполняет   вычисления,
использует  память  и  общается с внешним миром. В этой главе
поясняются такие понятия как прерывание, стек и порт.
     Практически весь материал этой главы полностью относится
к   уже  упоминавшимся  нами  трем  областям  интересов.  Это
объясняется  тем,  что  речь  в   основном   будет   тдти   о
функционировании   микропроцессора   8086/8088,   общего  для
IBM/PC, компьютеров, работающих под управлением  операционной
системы MS-DOS.
     
     3.1. Память,часть 1: что это такое и как осуществляется
чтение из памяти
     
     
     Одним  из основных элементов компьютера, позволяющим ему
нормально функционировать, является память. Внутренняя память
компьютера  -  это  место  хранения  информации, с которой он
работает. Внутренняя  память  компьютера  является  временным
рабочим пространством; в отличие от нее внешняя память, такая
как  файл  на  дискете,  предназначена  для   долговременного
хранения  информации.  Информация  во  внутренней  памяти  не
сохраняется при выключении питания.
     По  аналогии  с   конторской   работой   можно   назвать
микропроцессор  конторским  служащим,  а  память компьютера -
рабочим столом: пространство его используется  временно,  для
выполнения работы.
     Память компьютера организована в виде множества ячеек, в
которых могут храниться значения; каждая  ячейка  обозначется
адрсом.  Размеры  этих  ячеек  и,  собственно, типы значений,
которые  могут  в  них   храниться,   отличаются   у   разных
компьютеров.  Некоторые старые компьютеры имели очень большой
размер ячейки, иногда до 64 бит в каждой ячейке. Эти  большие
ячейки назывались "словами". Супер-копьютеры Крей и компьютер
Юнивак ориентированы на работу со словами.
     Трудность работы со словами большой длины заключается  в
том,  что  обычно программы работают не с целыми словами, а с
их частями. Поэтому большинство современных компьютеров, и  в
том числе все персональные компьютеры, используют значительно
меньший размер ячейки памяти, состоящей всего из  8  бит  или
"байта": Байт - это очень удобная единица информации, отчасти
потому что он позволяет хранить код одной буквы алфавита  или
одного  символа.  Поскольку  символ  занимает в точности один
байт, термины "байт" и "символ" часто используются в одном  и
том же смысле.
     Так как IBM/PC использует ячейки памти длиной восемь бит
или один байт, в памяти  могут  храниться  значения,  которые
можно выразить восемью битами. Это значения до двух в восьмой
степени или 256. Смысл величины, записанной в ячейку  памяти,
зависит  от способа ее использования. Можно считать, что байт
содержит код алфавитного символа - так называемый код  ASCII.
В  то  же  время его можно рассматривать и как число. Все 256
возможных   значений   могут   рассматриваться    либо    как
положительные  числа от 0 до 255, либо как числа со знаками в
диапазоне  от  -  128  до  +  127.  Кроме  того,  байт  может
использовать  как  часть  большого  объема  данных, например,
строки символов или двухбайтного числа.
     Для   удобства   манипулирования   символьными   данными
компьютеру необходимо чтобы коды символов преобразовывались в
байтовые величины. Большинство компьютеров,  включая  IBM/PC,
используют  код  ASCII,  американсткий  стандартный  код  дл[
обмена  информации.  *Юольшинство  компьютеров  фирмы   "IBM"
используют  другую  схему  кодирования символов, называющуюся
EBCDIC; системы ASCII и EBCDIC организованы  по  разному,  но
перекодировка  из  одной  системы  в другую большого труда не
представляет).
     В коде ASCII числовые значения присваиваются всем обычно 
используемым символам, таким как буквы алфавита,  строчные  и 
заглавные,   цифры,   знаки   пунктуации.   Несколько   кодов 
зарезервированы для управления, например, чтобы указать конец 
строки  символов. Эти специальные управляющие коды в основном 
имеют значения от CHR$(0)  до  CHR$(31).  Использование  этих 
специальных  кодов  IBM/PC  имеет  ряд  особенностей, которым 
посвящено приложение 4. 
     Код ASCII - это семибитовый код, имеющий  128  возможных
значений  кодов.  Стандартный  код  ASCII  обычно  использует
первые 128 из 256 возможных значений, помещающихся  в  байте.
Остальные  128  могут  использоваться  для  различных  целей,
образуя  "расширенный  набор"  символьных  кодов  ASCII.   Не
существует никаких стандартов использования расширенных кодов
и различные устройства компьютеров используют их  по-разному.
Дисплей  IBM/PC использует расширенный набор языков, отличных
от английского, различных математических  символов,  а  также
псевдографических  элементов,  которые можно использовать для
рисования. Программа, приведенная в листинге 1.1,  показывает
все специальные символы IBM/PC, а подробнее об их организации
сказано в главе 8.
     Стандартное для IBM/PC матричное устройство печати MX-80 
фирмы "Эндисон" преобразует коды символов расширенного набора 
ASCII  в  печатные  формы,  отличающиеся  от  изображений  на 
экране.  Если  запустить  программу 1.1, а затем использовать 
операцию  PrintScreen   (печать   экрана)   для   копирования 
содержимого  экрана  на  печатающее  устройство,  Вы  сможете 
сравнить экранный и  печатный  эквиваленты  одних  и  тех  же 
расширенных кодов ASCII. 
     Таблицы  стандартных  кодов  ASCII  и  расширенных кодов
ASCII для IBM/PC можно найти во многих местах.  Одна  из  них
приведена в конце руководства по Бейсику. Очень удобная форма
таблицы приведена в приложении C к  техническому  руководству
по IBM/PC.
     До  сих  пор  мы  рассматривали  побайтное использование
памяти, однако, часто для более сложных значений,  чем  может
уместиться  в одном байте используется несколько байт вместе.
Если необходимы строки символов, они сохраняются  в  соседних
ячейках  памяти,  по  одному  символу  на  байт; первый слева
символ записывается в первый байт, т.е.,  байт  с  наименьшим
адресом.
     Если  требуется  запомнить  целое  число  больше  одного
байта,  то  оно  записывается   в   несколько   байт,   также
расположенных   рядом.   Наиболее   распространенный   формат
использует  2  байта  или  16  бит,  что  очень  удобно   для
16-разрядного   процессора,   такого  как  8088.  В  терминах
микропроцессора 8088  двухбайтное  число  называется  словом.
Многие  команды  8088  срециально  разработаны  для работы со
словами. Могут  использоваться  и  более  длинные  форматы  -
трех-,  четырехбайтные  и  длиннее  -  но  они  не так широко
распространены как двухбайтные и  для  работы  с  ними  нужны
специальные программы.
     Когда  числа,  состоящие  из  двух  или нескольких байт,
хранятся в памяти микропроцессора  8088,  они  размещаются  в
ячейках  последовательно,  начиная  с  младшего  байта числа.
Такой   способ   несколько   непривычен    для    большинства
специалистов,  не  имевших  дела  с  микропроцессорами  фирмы
"Интел". Если Ваша программа работает с отдельными байтами  в
памяти, необходимо учитывать такой способ хранения.
     Арифметический  сопроцессор  8087  использует  несколько
специальных     форматов,     включающих      четырехбайтовый
целочисленный  формат  и  три  формата  с  плавающей запятой:
двухбайтный,  четырехбайтный   и   десятибайтный,   а   также
десятичный    формат   с   двадцатью   десятичными   цифрами.
Микропроцессор  8088  непосредственно   не   использует   эти
форматы,   но   если   к   IBM/PC   подключен  арифметический
сопроцессор 8087, эти форматы становятся как  бы  расширением
набора форматов данных.
     
     3.2. Память, часть 2: что такое адрес
     
     Каждая  ячейка  памяти имеет адрес, который используется
для ее нахождения. Адреса - это чмсла,  начиная  с  нуля  для
первой  ячейки  увеличивающиеся  по  направлению  к последней
ячейке памяти. Поскольку адреса - это те же числа,  компьютер
может  использовать  арифметические  операции  для вычисления
адресов памяти.
     Архитектура каждого компьютера  накладывает  собственные
ограничения  на  величину адресов. Наибольший возможный адрес
определяет обьем адресного пространства  компьютера  или  то,
какой  обьем  памяти  он может использовать. Обычно компьютер
использует  память  меньшего  обьема,  чем  допускается   его
возможностями    адресации.   Если   архитектура   компьютера
предусматривает   небольшое   адресное   пространство,    это
накладывает   суровые   ограничения   на  возможности  такого
компьютера.
     IBM/PC использует возможности адресации  микропроцессора
8088   полностью.   Адреса   в   8088  имеют  длину  20  бит,
следовательно, процессор позволяет адресовать два в двадцатой
степени байта или 1024 К.
     Такое  большое  адресное  пространствопозволяет свободно
использовать ресурсы памяти для  специальных  целей,  что  мы
увидим в следующем разделе. Перед этим необходимо разобраться
в том, как 16-разрядный компьютер  работает  с  20-разрядными
адресами  и какие ограничения это может наложить на программы
пользователя.
     Большая часть  арифметических  операций,  которые  может
выполнять  микропроцессор 8088, ограничивается манипуляцией с
16-разрядными числами, что дает диапазон  значений  от  0  до
65.535 или 64 К. Поскольку полный адрес должен состоять из 20
разрядов, необходимо было разработать  способ  управления  20
разрядами.  Решение было найдено путем использования принципа
сегментированной адресации. 
     Если  взять  16-ти  разрядное  число и добавить к нему в
конце четыре двоичных  нуля,  то  получится  20-ти  разрядное
число,  которое  может  использоваться как адрес. Добавлением
четырех  нулей  или  сдвиг  числа  влево  на  четыре  разряда
фактически  означает  умножение числа на 16 и теперь диапазон
значений  будет  составлять  1.024К.  К  сожалению,  число  с
четырьмя  нулями  в  конце может адресовать только одну из 16
ячеек памяти - ту, адрес которой оканчивается на четыре нуля.
Все остальные ячейки, адреса которых оканчиваются на любую из
остальных  16  комбинаций  из  четырех  бит,  не  могут  быть
адресованы при таком методое адресации.
     Для   окончательного   решения   проблемы   20-разрядной
адресации используются два 16-разрядных числа. Считается, что
одно  из  них  имеет  еще  четыре  нуля в конце (выходящие за
пределы разрядной сетки). Такое  как  бы  20-разрядное  число
называется сегментной частью адреса. Второе шестнадцатиричное
число не сдвигается на четыре разряда и используется в  своем
нормальном  виде.  Это  число называется относительной частью
адреса.   Сложением   этих   двух   чисел   получают   полный
20-разрядный  адрес,  позволяющий адресовать любую из 1.024 К
ячеек памяти в адресном пространстве IBM/PC. Сегментная часть
адреса  задает  ячейку  с  адресом,  кратным  16,  эта ячейка
называется   границей   параграфа.   Окончательное   значение
указывает   конкретную  ячейку  на  определеном  удалении  от
границы параграфа.Рисунок 3.1 показыает как это делается.
    Чтобы лучше усвоить этот момент, рассмотрим все еще  раз.
Полный  20-разрядный  адрес задается двумя частями, каждая из
которых представляет  собой  16-разрядное  число.  Сегментная
часть  адреса  обрабатывается  так, как будто он имеет четыре
дополнительных нуля  в  конце.  Эта  сегментная  часть  может
относиться  к  любой  части всего адресного пространства - но
она может указывать только на шестнадцатиричную  границу,  то
есть,  на адрес, оканчивающийся на четыре нуля. Относительная
часть адреса прибавляется к сегментной части, образуя  полный
адрес. Относительная часть адреса может задавать любую ячейку
памяти, отстоящую от ячейки, указываемой сегентной частью, не
более чем на 64К.
        

1-обычный    16-разрядный    регистр   адреса;   2-16бит   (4
шестнадцатиричные цифры) 4 бита на  шестнадцатиричную  цифру;
3-сдвиговый   регистр   сегмента;   4-объединенные   регистры
сегмента     адреса     и     сегмента;      5-дополнительный
шестнадцатиричный ноль; 6-результат - 20-разрядный адрес     
     
     Хотя относительная часть адреса могла бы задавать только
четыре последних цифры адреса, она принимает значения от 0 до
без единицы 64К. Большая часть манипуляций с адресами связана
с  относительной  частью  адреса.  Сегментная  часть   адреса
фактически  становится  базовым  адресом  для рабочей области
размером  ,;К,  которую  позволяет  адресовать  относительная
часть адреса.
     Имеется  удобный способ записи сегментированных адресов,
использование которого программой DEBUG (описанной в главе 6)
Вы  еще  увидите.  Кроме  того,  он  хорошо  прослеживается в
ассемблерных листингах, например в том,  который  приведен  в
приложении  А  к  техническому  руководсву фирмы IBM. Сначала
записывается  сегментная  часть  адреса,  после  нее  следует
двоеточие, а затем относительная часть адреса. Например, если
сегментная часть адреса (в шестнадцатиричной форме)  2222,  а
относительная  часть - 3333, то полный сегментированный адрес
будет записываться как  2222:3333.  Фактический  20-разрядный
адрес  будет  в  шестнадцатиричном виде иметь значение 25553,
получаемое таким простым сложением:
     
                      22220
                    +
                       3333
                   ____________
     
                     25553

     (В конце этого раздела мы  приведем  несколько  примеров
работы с сегментированными адресами на Бэйсике и Паскале).
     Для  работы  с сегментированными адресами микропроцессор
8088 имеет специальные  регистры  сегментов,  предназначенные
для  хранения  сегментной  части  адресов. Загрузив в регистр
сегмента некоторое значение, можно  адресовать  следующие  за
ним  64К  ячеек  памяти  .  Без изменения значения в регистре
сегмента компьютер может работать только  с  64К  байтами  из
общего  адресного  пространства  в  1.024К.  Путем  изменения
значения в регистре сегмента можно  адресовать  любую  ячейку
памяти.
     Чтобы иметь возможность в каждый момент времени работать
более чем с 64К памяти, в микропроцессоре 8088  предусмотрены
четыре  различных  регистра сегмента, каждый из которых имеет
особое  назначение.  Память   компьютера   используется   для
различных  целей  - часть ее занимает программа, другая часть
используется для хранения данных, с которыми в данный  момент
работает  программа.  Поэтому  два регистра сегмента выделены
для программы и для  данных.  Для  указания  базового  адреса
программного  или  кодового сегмента используется регистр CS.
Для указания сегмента данных  используется  регистр  DS.  Еще
одна  область  памяти,  используемая  для  специальных целей,
называется стеком и ее адрес указывается регистром стека  SS.
И,   наконец,  для  обеспечения  дополнительных  возможностей
адресации  имеется  регистр  дополнительного  сегмента   (или
сегмента расширения),  ES.
     Когда    программа    подготавливается   к   выполнению,
операционная система, такая как DOC,  выбирает  ячейки  каких
разделов  будут  использоваться  для размещения кодовой части
программ, данных и стека. В регистры  сегментов  CS,DS  и  SS
заносятся  адреса этих ячеек. При выполнении программы адреса
в этих регистрах позволяют находить нужные ячейки памяти. 
     Следует    понять,    что   эти   регистры   совсем   не
обязательнодолжны указывать на сегменты памяти, расположенные
далеко  друг  от  друга. Они могут указывать на любые ячейки,
находящиеся  далеко  или  близко  друг  от   друга   и   даже
располагающиеся  в  одном разделе. Если необходимо всего пару
тысяч байт для размещения программы и данных, кодовый сегмент
и  сегмент данных могут располагаться рядом. И хотя фрагменты
кодового  сегмента  и  сегмента   данных   используются   при
выполнении   программы   по-разному,   64К-байтные   области,
адресуемые  соответствующими  регистрами   сегментов,   могут
отсекаться.  На  рис.3.2  показано  как  эти  три  сегмента -
кодовый,данных и стека - могут использоваться и  как  области
этих сегментов могут пересечься.
     
        
     
1-регистр   сегмента;   2-указывает  64К  памяти; 
2-нам требуется; 3-16К кодовой части; 4-32К данных;
5-8К  стека;  6-мы  выделяем  для  них  место  в   памяти   и
устанавливаем значения соответствующих регистров;
7-регистры  обеспечивают доступ к большому обьему памяти, чем
необходимо; 8-избыток
     
     
     Если    программа    не   изменяет   содержимого   своих
регистров сегментов, то она  может  использовать  только  64К
данных  и  кодовую  часть обьемом 64К. С другой стороны, если
программа   будет   манипулировать    содержимым    регистров
сегментов,  то  она  сможет работать с данными любого обьема,
вплоть  до  1024К.  Может  использоваться  любой  из  режимов
работы,  но  на практике обычно фиксируют содержимое регистра
сегмента  данных  и  при  необходимости  изменяют  содержимое
регистра  кодового  сегмента. Такой способ организации работы
поддерживается   набором   команд    микропроцессора    8088,
обеспечивающим   очень   удобный   способ  загрузки  регистра
кодового сегмента CS, путем использования  команд  FARCALL  и
FARRET.
     Практические  результаты  такой организации выразились в
том, что ДОС и  языковые  процессоры  используют  программные
соглашения,  которые  позволяют  увеличивать  обьем  программ
практически неограниченно,  в  то  время  как  их  адресуемая
область   данных   ограничена  64К.  Вы  легко  заметите  это
ограничение, работая с Паскалем или компилятором Бейсика. Для
"встроенного"  интерпретатора  Бейсика  для IBM/PC собственно
выполняемой программой является сам интерпретатор, а  то  что
Вы  считаете  своей программой на Бейсике фактически является
частью   данных   интерпретатора.    Таким    образом,    для
интерпретатора Бейсика суммарный обьем кодовой части и данных
Вашей программы не должен превышать  64К,  которые  позволяет
адресовать регистр данных DS.
     Как  Бейсик,  так и Паскаль лишь до определенной степени
позволяют  манипулировать  сегментированными   адресами.   Вы
можете непосредственно изменять содержимое регистров CS,DS,SS
и ES -языковой процессор должен управлять  этими  регистрами,
иначе  все  может совершенно запутаться. Однако, определенный
способ использования в программах сегментированной  адресации
все же имеется.
     Ниже  приводится описание использования такого способа в
Бейсике. Раздел  сегмента  может  быть  определен  с  помощью
оператора   DEFSEG.   Некоторые  языковые  средства  Бейсика,
например,  операторы  PEEK  и  POKE,  работают   с   адресами
относительными к значению, заданному оператором DEFSEG.
     Например, если взять упоминавшийся выше адрес 2222:3333,
то на бейсике доступ  к  его  значению  может  осуществляться
следующим образом:
     
     10  DEFSEG=$H2222  'установить  значение сегмента равным
                         шестнадцатиричных 2222
     20 Х=PEEK(&H3333)' выбрать значение, смещенное  на  3333
                        шестнадцатиричных
     30 REM чисто для примера проверяем  в каком регистре за-
                        дан  код  буквы  и  если она в нижнем
                        регистре, то  переводим  ее в верхний
                        регистр
     40IF(CHR$(X)>="a")AND(CHR$(X)<="z")THEN POKE&H3333,(X-32) 
     

       
     Таким  образом,  в  программе  на Бейсике доступ к любой
ячейке памяти осущес твляется с помощью комбинации операторов
DEF  SEG  и  PEEK  или  POKE.  Работа  с  ними  встречается в
листингах  программ  1.1,  3.1  и  8.1,  использующих   такую
возможность Бейсика для различных целей. 
     Паскаль   разрешает   аналогичный   способ  программного
использования  сегментированной  адресации,  правда  в  более
унифицированном  и  гибком  виде чем Бейсик. На Паскале можно
определить переменную как сегментированный адрес,например:
     
     VAR пример_адреса : adasmem,
     
а затем непосредственно задать его сегментную и относительную
части ('.s' и '.r', соответственно):
     
     пример_адреса.s : = # 2222;
     пример_адреса.r : = # 3333;
     
     Когда все эти присваивания выполнены, можно осуществлять
доступ к памяти с помощью указателя сегменитрованного адреса:
     
     x : = пример_адреса^;
     if(chr(x)> = "a") and (chr(x)< = "z") then
     пример_адреса^ : = x - 32;
     
     
     
     3.3. Организация памяти IBM/PC
     
     
     Имея адресное пространство свыше  миллиона  байт  IBM/PC
позволяет более удобно и более гибко использовать память, чем
большинство других, меньших  персональных  компьютеров.  Весь
объем памяти распределен довольно интересным образом. С одной
стороны,  резервирование  определенных  ячеек  памяти   может
наложить  ограничение  на  возможные применения компьютера. В
IBM/PC резервируется несколько  областей  в  верхних  адресах
памяти.  Эти  область  имеют  особое назначение, а все нижние
адреса оставлены для свободного использования. Таким  образом
сочетаются достоинства использования зарезервированных блоков
памяти и сохранения как  можно  большего  объема  памяти  для
свободного использования.
     На   рис.  3.3.  показана  простая  схема  распределения
памяти. Верхняя четверть  общего  объема  памяти,  начиная  с
ячейки  C  000  и  до  конца,  практически  всегда занимается
постоянным запоминающим устройством или  ПЗУ.  (В  бальнейшем
все  упомиющиеся  адреса  будут  без специального напоминания
даваться в шестнадцатиричном виде.) Фактически  ПЗУ  занимает
только верхние 8К, начиная с адреса FE00, в которых находится
система BIOS (подробно описанная в главе 6). Система  BIOS  в
ПЗУ  включает  все основные служебные процедуры IBM/PC, в том
числе тестовые программы, которые запускаются  при  включении
компьютера.
     Следующие  (если  идти сверху вниз) 32К используются для
хранения  интерпретатора  Бейсика.  Бейсик-ПЗУ  начинается  с
ячейки  F600  и  заканчивается  непосредственно перед BIOS. В
главе 6 описывается интепретатор Бейсика в ПЗУ.  В  принципе,
любая   часть   адресного   пространства  может  быть  занята
постоянной памятью, но  в  соответствии  с  общими  правилами
организации  памяти  IBM/PC,  адреса  ПЗУ  должны быть больше
C000. Как упоминалось в главе 2,  в  системном  блоке  IBM/PC
установлено  пять  микросхем  ПЗУ и одно свободное гнездо для
установки микросхемы. Эти  пять  микросхем  содержат  BIOS  и
Бейсик.  Каждая  микросхема  имеет  емкость  8К. Еще 8К можно
добавить с помощью свободного гнезда и  начальный  адрес  для
них   будет   равен   F400,   так   чтобы  они  располагались
непосредственно перед Бейсиком.
     
 
1-шестнадцатиричный адрес; 2-память, размещенная в  системном
блоке;  3-память,размещаемая  в  блоке  расширения;  4-предел
обычной памяти в 256К; 5-свободная  часть;  6-зарезервирована
для   дисплеев;   7-монохромный   дисплей;   8-свободна   для
использования  дисплеями;  9-цветной   графический   дисплей;
10-область    дисплейной    памяти;   11-область   возможного
добавления ПЗУ; 12-Бэйсик-ПЗУ; 13-BIOS-ПЗУ; 14-нижние адреса;
15-верхние адреса
     
     
     Ниже  области  ПЗУ располагается большой сегмент памяти,
предназначенный для поддержки экранного режима дисплеев.  Для
хранения   информации,  отображаемой  на  экране,  необходимо
использоватьспециальную   область   памяти,   которая   может
располагаться  как внутри дисплея, так и внутри компьютера, с
которым он соединен. В IBM/PC экранная память входит в  общее
адресное  пространство  компьютера  (хотя  конструктивно  она
размещается на плате расширения для дисплея). В  главе  8  мы
более подробно рассмотрим размещение и использование экранной
памяти.
     Блок экранной памяти начинается с адреса B000 и занимает
64К,  вплоть  до адреса C000. Этот блок делится на две части.
Нижняя половина, начинающаяся  с  адреса  B000,  используется
монохромным дисплеем. Верхняя половина, начинающаяся с адреса
B800, используется цветным графическим дисплеем. В главах 8 и
9  более  подробно описывается структура и использование этой
памяти. 
     
     Ни   один  из  дисплейных  адаптеров  не  требует  и  не
использует все 32К, выделенные для них.  Монохромный  дисплей
использует всего 4К, а цветной графический дисплей использует
16К.  Оставшаяся  часть   памяти   в   настоящее   время   не
используется,  но  может  понадобиться  для более совершенных
дисплейных адаптеров.
     Фактически, для  дисплейных  адаптеров  выделено  больше
памяти,   чем   эти   64Кот   B000   до  C000.  Блок  в  64К,
предшествующий им, также  зарезервирован.  В  соответствии  с
документацией   IBM/PC  блок,  начинающийся  с  адреса  A000,
резервируется двумя способами. Первые 16К, от A000 до  A4000,
зарезервированы совершенно таинсвенным образом, не имеется ни
малейшего указания на то, для чего это сделано. Остальные 48К
этого  блока  от A400 до B000, входит в обалсть 112К, которая
считается  зарезервированной  для  экранной   памяти.   Таким
образом,  вся  область экранной памяти располагается с адреса
A400 до C000.
     Можно предположить, что эта  большая  область,  особенно
18К  в  блоке  A000,  будут использоваться каким-нибудь новым
дисплеем  с  высокой   разрешающей   способностью,   которому
потребуется  больше  памяти чем для обычного монохромного или
цветного графического дисплея.  Непонятно  только  назначение
первых  16К  блока  A000,  не обозначенных как часть эуранной
памяти.
     Объем памяти, расположенной ниже адреса A000, составляет
64К,  которык предназначены для обычного использования памяти
компьютера. Первые 64К,  до  адреса  1000,  располагаются  на
основной  системной  плате IBM/PC, а все остальные микросхемы
памяти размещаются в блоках расширения. По  сообщениям  фирмы
"ИБМ",  IBM/PC поддерживает всего 256К памяти, но этот предел
связан только с тестами BIOS, которые при запуске  компьютера
проверяют  такой объем памяти. Всегда можно подключить больше
чем 256К памяти.
     Вся обычная оперативная память,  подключенная  к  Вашему
компьютеру,  располагается  в нижних адресах общего адресного
пространства. Вы можете подключить такой объем  памяти  какой
Вам  необходим  в  пределах, накладываемых зарезервированными
адресами.  Независимо  от  того,  подключено  ли   к   Вашему
компьютеру  48К  или  576К,  они всегда размещаются начиная с
адреса 0000.
     Таким образом, оперативная память всегда занимает нижние
адреса пространства, а постоянная память - в верхних адресах.
Между ними располагается экранная память. Между  всеми  этими
разделами   могут  быть  промежутки  -  промежуток  от  конца
оперативной памяти до  начала  экранной  памяти  и  от  конца
экранной  памяти  до  начала  ПЗУ.  Это  неиспользуемая часть
памяти IBM/PC.
     Оперативная  память  временно  используется  работающими
программами  и  их  данными.  Часть этой памяти, ее начальные
адреса,  используются  для  нужд  самого  микропроцессора,  а
другие небольшие фрагменты используются операционной системой
и   интепретатором   Бейсика.   Оставшаяся    память    может
использоваться любыми программами.
     Самая  нижняя  часть  памяти,  начинающаяся  с  нулевого
адреса и занимающая примерно  1500  байт,  предназначена  для
хранения   необходимой  рабочей  информации  для  компьютера.
Первая  часть  этой  области  содержит  вектора   прерываний,
которые более подробно будут рассмотрены в разделе 3.5. После
векторов прерываний располагается информация, необходимая для
управляющих   процедур   BIOS,   операционной  систмы  ДОС  и
интепретатора Бейсика,  а  также  их  рабочие  ячейки.  После
зарезервированной  области в нижних адресах памяти начинается
рабочая  область,  в  которую  загружаются  программы  и  где
хранятся их данные.
     Можно  исследовать  память  IBM/PC  и  установить, какие
блоки  используются  и   где   они   размещены   в   адресном
пространстве.  Программы  могут  пытаться  выполнять чтение и
запись по  любым  адресам  памяти.  Можно  предположить,  что
обращение   к  неподключенной  памяти  приведет  к  появлению
сигнала ошибки, но на практике этого не  происходит.  Причина
этого   проста   -  работа  микропроцессора  8088  с  памятью
заключается в обращении к каналу ввода/вывода, который описан
в  главе  2,  и  ожиданием  результата.  Даже  если память не
подключена, микропроцессор не замечает разницы.
     Однако, можно достаточно просто  проверить  наличие  или
отсутствие  памяти  по  определенному адресу. Один из методов
заключается  в  чтении  из  различных  облас  тей  памяти   с
последующей    проверкой    результатов.    Непродолжительные
эксперименты показывают, что при большинстве методов  чтения,
как  через  DEBUG,  так  и  с  помощью средств языка Паскаль,
результатом  всегда  оказывается  байт  со  всеми  единичными
битами;  что соответствует шестнадцатиричному значению FF или
CHR$(255).
     Такой  результат  никого  не  должен удивлять - ведь при
чтении несущетвующей памяти наиболее вероятно  получить  либо
все  нули,  либо все единицы. По какойто причине, которая мне
досих пор не понятна, интепретатор Бейсика всегда  возвращает
значение  CHR$(233).  Результаты  не  совсем однозначны, но в
большинстве случаев Бейсик  возвращает  именно  это  странное
значение, CHR$(233), при чтении неподключенной памяти.
     Такое  свойство  можно  использовать  для проверки того,
какая  часть  адресного  простанства  активна.  Листинг  3.1.
показывает простую программу на Бейсике, которая считывает по
нескольку байт из каждого килобайта памяти и сравнивает их со
значением CHR$(233). Если Вы запустите эту программу на своем
компьютере,  то  она  покажет  какой  объем  памяти  к   нему
подключен.  Рисунок  3.4 показывает результат выполнения этой
программы на IBM/PC, который я использовал при написании этой
книги. Посмотрим о чем они говорят.
     Во-первых, отметим, что были обнаружены три блока памяти
- то есть, именно столько, сколько должно быть  подключено  к
IBM/PC.  Первый  блок начинается с адреса 0 или самого начала
памяти. Это обычная, оперативная память компьютера. В  данном
конкретном компьютере первый блок имеет размер 576Кбайт. Сюда
входят 64К в системном блоке и еще 512К в блоке расширения.
     Второй блок активной памяти начинается  с  адреса  B000.
Это  память,  используемая  адаптером  монохромного  дисплея.
Поэтому можно сделать вывод, что данный компьютер работает  с
монохромным  дисплеем,  а не с цветным графическим адаптером.
Заметим, что наша исследовательская  программа  считает,  что
эта  память  занимает  32К, в то время как в действительности
монохромный адаптер включает включает всего  4Кбайта.  Лишние
28К обнаруженные программой, можно, вероятно, отнести на счет
побочных  эффектов,  связанных  с   работой   схем,   которые
поддерживают  реальные  4К  памяти.  Выполнение  той же самой
программы в системе с  цветным  графическим  монитором  также
обнаруживают 32К памяти, хотя реально используется всего 16К.
     После памти адаптера дисплея программа обнаруживает ПЗУ,
занимающее верхние адреса  памяти.  В  этом  последнем  блоке
программа  обнаруживает  ровно  столько  байт,  сколько в нем
действительно имеется.
     
     Программа 3-1: Найти и отобразить активную память
     Потерпите - выполнение этой программы занимает 65 сек
     (Адреса начала сегментов приведены  в  шестнадцатиричном
виде)
     Активная память начинается с  0
                     заканчивается 8FFF 576К байт
                                       (589824 байта)
     Активная память начинается с  B000 
                     заканчивается B7FF 32К байт 
                                       (32768 байта)
     Активная память начинается с  F000
                     заканчивается FFFF 64К байт
                                       (65536 байт)
     Конец работы
     
     
     Рис 3.4. Результат работы программы 3.1
     
     Хотя  программа  3.1  интересна  и  сама  по  себе,  для
исследования  памяти  Вашей  систем,  но  она   также   может
послужить   хорошим   примером   тех   возможностей,  которые
откроются перед Вами, когда Вы досконально изучите компьютер.
Фирма   "IBM"   не   сообщает,   что   Бейсик   считывает  из
отсутствующей памяти именно значение 233, и никто не объяснял
мне,  как  проверять память. Однако, имея интерес и некоторую
настойчивость   в    исследованиях,  я  написал    программу,
приведенную в конце главы, листинг 3.1. Именно к такой работе
я Вас и  призываю.  Изучайте  Вашу  систему,  исследуйте  все
детали - и тогда Вы приобретете глубокие познания о принципах
работы IBM/PC.
     Кстати, следует заметить, что эта программа  может  дать
странные   результаты,   если   используются   платы  памяти,
изготовленные  не  фирмой  "IBM".  Это   еще   один  признак,
позволяющий больше узнать о Вашей системе.

     
     3.4. Сверхоперативная память - регистры
     
     Помимо    памяти,   для   временного   хранения   данных
микропроцессор  8088   использует   еще   и   регистры,   что
существенно  ускоряет  работу.  Сейчас  мы  кратко рассмотрим
использование регистров.
     Наиболее  полное  писание  регистров   можно   найти   в
руководствах   по   системе   команд   и   языку   ассемблера
микропроцессора 8076. В данном разделе содержится  достаточно
сведений  для того, чтобы Вы не терялись, встретив упоминание
названий регистров в любом контексте.
     Микропроцессор   имеет    четыре    шестнадцатиразрядных
регистра  общего  назначения,  называемых  AX,  BX,  CX и DX.
Каждый из них может  быть  разделен  на  два  восьмиразрядных
регистра,  указанием  старшей  (H-high)  или  младшей (L-low)
части полного (X) регистра.  Таким  образом,  восьмиразрядные
регистры  называются  AH,  AL,  BH,  BL,  CH,  CL,  DH  и DL.
Поскольку восьмиразрядные регистры непосредственно связаны  с
16-разрядными,  операция  записи  шестнадцатиричной  величины
ABCD в регистр AX эквивалентна записи величины AB  в  регистр
AH и величины CD регистр AL.
     Хотя  все эти регистры имеют общее назначение, каждый из
них  имеет   определенную   специализацию.   Например,   если
некоторая  операция  должна  повторяться  нес  колько раз, то
регистр содержит счетчик повторений.
     Мы уже упоминали четыре  регистра  для  сегментированной
адресации:CD  для  кодового сегмента, DS для сегмента данных,
SS для сегмента стека  и  ES  для  досполнительного  сегмента.
Относительная часть сегментирванного адреса может храниться в
любом регистре и использоваться вместе с  сегментной  частью,
которая  должна  находиться  в  одном из регистров сегментов.
Текущий адрес в выполняемой программе  образуется  содержимым
регистров  IP  (счетчик  команд)  и CS. Текущий адрес в стеке
образуется  содержимым  регистра  указателя  стека   (SP)   и
регистра сегмента SS.
     Для  адресации  данных  вместе  с  регистром сегмента DS
могут использоваться разные регистры.  Часто  для  этой  цели
служит  регистр  DX.  Два специальных регистра, DI и SI также
используются свместно с регистром DS. При работе со  строками
байт,  регистры  SI  и  DI используются для хранения индексов
исходной и приемной строк относительно регистра  DS.  Регистр
указателя  базы  (BP)  может  спользоваться в качестве адреса
относительно регистра SS.
     
     3.5. На что необходимо обратить внимание - прерывания
     
     омпьютер должен обладать  способностью  реагировать  на
события,  происходящие  вне  его  микропроцессора,  например,
чтобы  воспринимать  информацию,   вводимую   с   клавиатуры.
Существует  два способа организации такой реакции.Один способ
состоит  в  постоянном   ожидании   события.   Такой   способ
называется  "сканированием" или "опросом" и такой опрос может
занимать большую  часть  времени  компьютера.  Другой  способ
позволяет  компьютеру спокойно выполнять свою работу, пока не
произойдет событие,  требующее  его  внимания.  Такой  подход
называется    использованием    "прерываний".   использование
прерываний позволяет наиболее эффективно организовать  работу
компьютера,   поскольку   время  центрального  процессора  не
расходится вхолостую на ожидание.
     Какие  примеры  прерываний  можно  было   бы   привести?
Например, прерывание возникает, когда Вы нажимаете клавишу на
клавиатуре. Другое прерывание вырабатывает таймер, встроенный
в   IBM/PC.  Таймер  прерывает  работу  микропроцессора  8088
восемнадцать раз в секунду. Операционная система ведет отсчет
времени  дня просто подсчитывая эти прерывания таймера; время
дня можно вычислить по количеству  прерываний  таймера  после
последней   полуночи.   Еще  один  вид  прерываний  формирует
контроллер гибких дисков, сообщая процессору,  что  очередная
дисковая операция наконец завершилась. Поскольку эти операции
значительно  медленнее  чем  работа  самого  микропроцессора,
выгода состоит в том, что процессор может не ждать завершения
дисковой операции и продолжать вычисления до  тех  пор,  пока
контроллер  выработает  прерывание,  указывающее что операция
завершена. 
     Основная идея прерываний  заключается  в  том,  что  все
требующее  внимания  процессора, должно сообщать ему о себе в
форме  прерывания.  Использование  прерываний  дает  огромные
преимущества.  Если ничто не требует внимания процессора, - а
так обстоит дело большую часть времени,  -  то  процессор  не
тратит времени на проверку наступления событий, требующих его
вмешательства.С  другой  стороны,  если  возникает   событие,
требующее   внимания   немедленно,  оно  немедленно  и  будет
обслужено, поскольку прерывания обычно обслуживаются сразу же
после их возникновения.
     Иногда  бывает  необходимо,  чтобы  работа процессора не
прерывалась, например, при  выполнении  какой-либо  критичной
операции.   Для   этого   у   микропроцессора   8088  имеется
специальная команда, которая позволяет отложить  обслуживание
прерываний,    запоминая    их,    и   парная   ей   команда,
восстанавливающая нормальный режим  обслуживания  прерываний.
Когда  прерывания запрещаются запрос прерываний не теряется -
он запоминается  и  будет  обслуживаться,  как  только  будут
разрешены прерывания.
     Обычно  прерывания  не  запрещаются  на  сколько  нибуть
продолжительное время. Прерывания допустимо запрещать лишь на
очень короткие промежутки времени, необходимые для выполнения
некоторых  внутренних  операций  процессора,   состоящих   из
небольшого  числа  команд.  Типичным примером таких операций,
которые не могут быть  прерваны  на  полпути,  может  служить
загрузка   нового   набора  значений  в  регистры  сегментов.
Поскольку эти регистры необходимы для правильной работы любой
программы,  нарушение согласованности загрузки в них значений
может  привести  к  полной  неразберихе,  поэтому  необходимо
запретить прерывания на время загрузки в них новых адресов.
     Чтобы  привести  небольшой  пример  того,  к  чему может
привести  запрет  прерываний,   рассмотрим   две   программы,
названные  BEEP  и  WARBLE.  Если  у Вас есть пакет программ,
прилагающийся  к  этой  книге,  Вы  найдете  в  нем  обе  эти
программы, готовые к использованию. С помощью макроассемблера
можно получить эти программы из ассемблерного  листинга  3.2,
приведенного  в  конце  главы.  Обе программы: BEEP и WARSLE,
генерируют звуки  с  помощью  динамика  IBM/PC.  (О  том  как
генерируются  звуки  будет  рассказано в главе 11.) Каждая из
программ  генерирует  чистый   непрерывный   звук   в   одной
тональности,  но  программа  WARBLE  не запрещает прерывания.
Поэтому она прерывается таймером восемнадцать раз в секунду и
хотя  прерывания  обслуживаются очень быстро, звук получается
вибрирующим.  Программа  BEEP  запрещает  прерывания  и  дает
непрерывный  звук.  Запустите обе программы и Вы почувствуете
результат запрета прерываний.
     Механизм перывания работает следующим  образом:  каждому
из  основных  типов прерываний присвоен свой номер. Например,
прерывание таймера имеет номер 8,  гибкие  диски,  используют
номер  14.  В самом начале оперативной памяти IBM/PC хранится
таблица с адресами программ, которые  должны  вызываться  при
возникновении  различных  прерываний.  Эти адреса должны быть
полными сегментированными адресами, так что они  занимают  по
два  слова  или  по  четыре  байта  каждый. Эти адерса иногда
называются векторами прерываний. Прерывание с номером 0 имеет
вектор,  хранящийся  в ячейке с нулевым адресом, прерывание !
имеет свой вектор в ячейке 4 и так  далее.  Когда  происходит
прерывание  номер  "X",  вектор,  хранящийся  по  адресу  4X,
загружается в регистры адреса программы, т.е., регистры CS  и
IP,и  компьютер  начинает  выполнять  программу  обслуживания
прерывания, которая размещается по этому адресу.    
Когда    обработка    прерывания   заканчивается,   программа
обработки   возвращает    управление    программе,    которая
выполнялась  в  момент  возникновения  прерывания,  с помощью
специальной команды IRET или "возврат из  прерывания".  Чтобы
такой возврат мог быть выполнен, необходимо сохранить в стеке
текущие адреса прогрвммы до  загрузки  в  регистры  CS  и  IP
вектора прерывания.
     Концепция  прерывания была разработана для практического
решения проблемы взаимодействия компьютера с  внешним  миром.
Однако,  тем  не  менее  вскоре  оказалось, что прерывания не
менее полезны для организации внутренней  работы  компьютера.
Это  привело  к  разработке  трех  типов  прерываний, которые
получили названия аппаратных, логических и программных. Между
ними  нет  принципиальной  разницы,  однако  их использование
разделит их на три отдельных категории.
     Аппаратные  прерывания  мы   уже   рассмотрели   -   они
вырабатываются  устройствами, требующими внимания процессора.
В IBM/PC  таких  прерываний  на  удивление  мало.  Во-первых,
имеется так называемое немаскируемое прерывание, используемое
для сообщения об отказе питания, оно имеет  номер  2.  Далее,
прерывание  8  используется таймером, номер 9 - клавиатурой и
14 -  контролером  гибких  дисков,  всего  четыре  аппаратных
прерывания.  Имеется  также  семь  зарезервированных  номеров
прерываний, 6, 7, с  10  по  13  и  15,  которые  могут  быть
испоьзованы  в  дальнейшем,  если  возникнет  необходимость в
дополнительных  аппаратных  прерываниях.  Два  из  этих  семи
прерываний   уже   нашли   свое   назначение,  прерывание  12
зарезервировано для адаптера связи, а  прерывание  15  -  для
интерфейса устройства печати.
     Логические   прерывания  формируются  самим  процессором
8088, когда он встречает какое-либо необычное условие.  Таких
прерываний  предусмотрено  четыре. Прерывание 0 возникает при
попытке  деления  на  ноль.  Прерывание  1  используется  для
управления  пошаговым  режимом  работы  микропроцессора,  при
котором  команды  выполняются  по   одной.   Это   прерывание
выставляется  отладчиками для пошагового выполнения программ.
Прерывание 3 вырабатывается командой  установки  "контрольных
точек",  которая также используется при отладке. Прерывание 4
формируется при возникновении условия переполнения, например,
если   результат  арифметической  операции  не  помещается  в
регистр.  Таким   образом,   четыре   логических   прерывания
распадаются  на  две  пары:  одна для арифметических операций
(деление  на  ноль  и  переполнение)  и  вторая  для  отладки
программ (шаговый режим и контрольные точки). 
     Наиболее    интересны   программные   прерывания.   Если
программа должна воспользоваться услугами  другой  программы,
она  должна  передать  управление  этой процедуре. Обычно это
делается  с  помощью  команды  CALL.  Для  вызова   процедуры
программа должна знать ее адрес, а вызываемая процедура может
не знать  адреса  вызывающей  программы,  поскольку  механизм
вызова автоматически генерирует адрес возврата, который будет
использован  вызываемой  программой   после   завершения   ее
выполнения.  Образно  говоря,  для  перехода к подпрограмме и
возврата из нее  достаточно  купить  билет  в  один  конец  -
обратный  билет  предоставляется  бесплатно. Идея организации
программных прерываний должна позволять свободный переход и в
прямом  и  в  обратном направлении, то есть иметь возможность
вызвать подпрограмму и получить управление обратно  после  ее
завершения,  так  чтобы ни одна из сторон не могла не знать о
местонахождении (адресе) другой.
     Программные прерывания  обеспечивают  такую  возможность
путем  выработки  прерывания самой программой. Например, если
программе необходимо вычислить время дня,  ей  совершенно  не
требуется знать адрес программы подсчета времени - достаточно
знать только, что программа подсчета времени дня  запускается
программным прерыванием 26.
     Программные  прерывания  используются  для  вызова  всех
служебных функций, представляемых обычным пользователям.  Эти
функции включают все процедуры системы BIOS и ПЗУ и служебные
процедуры ДОС.  Программные  прерывания  используются  вместо
непосредственных  адресов  по  двум причинам. Наиболее важная
причина состоит в обеспечении возможности изменения служебных
процедур,   вызываемых   с   помощью   прерываний.  Изменение
процедуры обычно приводит к изменению ее размера и размещения
в  памяти. Если процедура вызывается с помощью прерывания, то
использующие  ее  программы  не  требуется  изменять,   когда
изменилась процедура.
     Другая  причина использования программных прерываний для
вызова процедур связана с возможностью их замены.  Рассмотрим
пример.  Как  Вы  узнаете из главы 8, служебные процедуры для
обслуживания  дисплея  выдают  звуковой  сигнал   с   помощью
динамика  IBM/PC,  каждый  раз  когда  выдается  код CHR$(7).
Предположим, что Вам  необходимо  подавить  выдачу  звукового
сигнала.  Для  этого  можно написать программу, которая будет
проверять какие символы выдаются на  экран  и  при  появлении
кода  CHR$(7) заменяет его пробелом. После окончания проверки
эта программа должна передавать управление обычной  процедуре
обслуживания   дисплея.Фактически,  нужно  сделать  небольшое
добавление перед стандартной процедурой обслуживания дисплея.
Чтобы  задействовать эту программу необходимо заменить вектор
прерывания дисплея (прерывание 16) адресом Вашей программы.
     Прогаммные прерывания очень  важны  для  работы  IBM/PC.
Большая  часть этой книги будет посвящена их более подробному
описанию. В главе 4 описываются  прерывания  системы  BIOS  в
ПЗУ.  Чтобы  Вы  могли  извлечь  максимальную  пользу из этих
системных  функций,  пакет  программ,  прилагаемый  к  данной
книге,  содержит  полный  набор  интерфейсных  процедур,  как
ассемблерных, позволяющих  осуществлять  доступ  к  служебным
процедурам  по  прерыванию  из  любых языков программирования
(включая Бейсик и Паскаль), так и вспомогательных процедур на
Паскале,  существенно  облегчающих использование ассемблерных
процедур.
     Прежде чем завершить рассмотрение прерываний, необходимо
упомянуть  еще об одном необычном применении таблицы векторов
прерываний. Таблица векторов  прерываний,  располагающаяся  в
самом начале оперативной памяти, предназначенная для хранения
полных  сегментированных  адресов  программ,  которые  должны
обслуживать  соответствующие  прерывания.  Однако,  в  IBM/PC
использование   таблицы   векторов   несколько   шире.   Хотя
считается, что таблица должна хранить только адреса программ,
разработчики  IBM/PC  сочли  ее  очень  удобным  местом   для
хранения  адресов  трех  элементов, которые вовсе не являются
программами. Это адреса очень важных системных  данных.  Идея
заключается   в  том,  чтобы  использовать  таблицу  векторов
прерываний  в  качестве  унифицированного  хранилища   важных
сегментированных адресов - в первую очередь, конечно, адресов
программ, но, если необходимо, то и  данных.  Таким  образом,
три  номера  прерываний,  29,  30  и  31  не  используются  и
соответствующие  им  вектора  в  таблице  обнуляются,   чтобы
подготовить  место  для  хранения  адресов трех важных таблиц
данных. Естественно,  что  эти  номера  прерываний  не  могут
использоваться: если программа запросит прерывание с номерами
29, 30 или 31, то управление будет передано в одну из  таблиц
данных, которая начнет выполняться как программа.
     В  главе 6 мы более подробно рассмотрим ПЗУ и установим,
что это за таблица. Затем мы рассмотрим их по одной, в главах
7, 8, 9.
     
     
     3.6. СТЕК
     
     
     Стеки  -  это  наиболее  интересные  и полезные средства
современных   компьютеров.   Вместе   с   прерываниями  стеки
обеспечивают  эффективность работы компьютеров.
     Что такое стек? Стек - это место,  в  котором  компьютер
хранит  рабочие  величины, так что один набор величин никогда
не смешивается с другим набором.
     Стек получил свое имя благодаря метафоре, которую  часто
используют  для  описания его работы. Представьте себе стопку
тарелок, например, таких которые используются  в  кафетериях,
где    тарелки   находятся   на   подпружиненной   платформе,
перемещающейся вверх и вниз. Если  нужно  добавить  в  стопку
(по-английски  stack)  чистые тарелки, которые были в стопке,
опускаются вниз. Когда кто-нибудь снимает тарелку сверху, вся
стопка  поднимается  вверх.  Тарелки используются по принципу
"последним вошел - первым вышел".
     Когда компьютер занят работой  и  поступает  прерывание,
необходимо   место  для  того,  что  бы  заполнить  состояние
компьютера до начала  обработки  прерывания.  Если  еще  одно
прерывание   поступит   в   процессе  обработки  первого,  то
необходимо запомнить и  эту  информацию.  Когда  обслуживание
второго  прерывания  завершится,  комьютер должен вернуться к
выполнению своей последней перед прерыванием работы, в данном
случае  к  обслуживанию  первого прерывания. Для обслуживания
прерываний и  для  многих  других  операций,  которые  должны
выполняться  по  принципу  перехода к последней из отложенных
операций, наиболее  естественным  средством  для  запоминания
состояния компьютера будет стек.
     Организация стека в IBM/PC  основана  на  выделении  под
стек  определенной области оперативной памяти и использовании
специального регистра сегмента стека, SS, указывающего адреса
этой  области  памяти.  Вершина  стека указывается содержимым
специального регистра, называемого указателем стека SP.  Стек
компьютера,  в  отличие  от подпружиненной стопки тарелок, не
перемещается физически, а остается на месте. Зато  изменяется
адрес вершины стека, указываемый содержимым регистра SP.
     Данные  помещаются  в  стек  компьютера  операцией PUSH,
извлекаются операцией POP.
     Когда возникает  прерывание,  адрес  текущей  программы,
хранящийся  в  регистрах  CS  и  IP, помещается в стек, затем
адрес процедуры обслуживания  прерывания  загружается  в  эти
регистры и начинается выполнение данной процедуры. До ячейки,
указываемой регистром SP (указателем стека), хранятся  данные
всей  предыдущей  работы,  ожидающей своего возобновления. За
указателем  стека  находится  свободное  пространство  стека,
которое    может   использоваться   процедурой   обслуживания
прерывания, если ей требуется дополнительная рабочая область.
Если   возникнет   еще   одно   прерывание,  новая  процедура
обслуживания  найдет  для  себя  свободную  область  в  стеке
несколько дальше.
     Когда     завершается     очередная    процедура,    она
освобождается.  Сначало  из  стека  извлекаются  все  рабочие
значения,   а   затем  извлекается  адрес  точки  приостанова
предыдущей процедуры, который загружается в регистры CS и IP.
В  процессе  выполнения всех этих действий механизм работы со
стеком  автоматически  поддерживает   последовательность   их
выполнения.  Стеки  используются  не  только для обслуживания
прерываний, но и при вызовах одних программ другими. Как  при
вызовах,  так  и  при  обслуживании  прерываний принцип один:
выполнявшаяся работа должна быть запомнена на  время,так  что
бы   можно  было  начать  новую.  Когда  новая  работа  будет
завершена,  необходимо  вернуться  к  выполнению   старой   в
порядке, обратном тому в котором работа приостановлена.
     При  вызове  подпрограмм  часто  возникает необходимость
передавать им параметры, что можно сделать с помощью стека. В
третьем приложении к этой книге описывается стыковка программ
на Паскале с программами на ассемблере и там  можно  увидеть,
как стек используется для передачи параметров.
     Стеки  настолько существенны для работы компьютеров, что
можно только удивляться их относительно недавнему включению в
конструкцию   компьютеров.  Серия  компьютеров  360,  которая
являлась основной продукцией фирмы "IBM" начиная  с  1960-тых
годов,   не   реализовывала   концепцию   стека,  что  сильно
отразилось  на  возможностях  всей  этой  серии.   Существует
красивая   легенда   о  том,  что  руководитель,  исключивший
стековую архитектуру из конструкции компьютеров фирмы  "IBM",
был в последствии "сослан" во внутрифирменный аналог Сибири.
     Использование   стеков  может  быть  гораздо  шире,  чем
описывалось выше. Микропроцессор 8088 использует стек  только
для хранения контекста приостановленных программ. Для этой же
цели стек использует большинство компьютеров. Можно,  однако,
полность   переориентировать   способ   работы  компьютера  с
командами и  данными,  так  что  все  будет  основываться  на
использовании  стека.  Такая  архитектура, ориентированная на
использование стека,  была  разработана  фирмой  "Барроуз"  и
все,  кто  хочет   понять   на   сколько   радикально   может
отличаться   компьютер   с  такой  архитектурой,  от  обычных
компьютеров, подобных IBM/PC, может  обратиться  к  описаниям
компьютеров фирмы "Барроуз".
     Имеется   одна   подробность   в   использовании   стека
микропроцессором 8088, о которой необходимо знать,  если  Вам
потребуется  воспользоваться  содержимым  стека или проверить
рабочий стек. Стек продвигается от верхних  адресов  памти  к
нижним.  Это  означает  ,  что  старое содержимое стека имеет
большие абсолютные адреса памяти,  чем  указатель  стека  SP.
Так,   например,   чтобы   извлечь   параметры  подпрограммы,
помещенные в стек, используются положительные смещения (эт  о
описано  в 3 приложении к этой книге). Что касается свободной
части стека, к которой  обычно  обращаются  только  командами
записи  или  извлечения  из  стека,  а  не  по прямому адресу
памяти, то для нее потребовалось  бы  отрицательное  смещение
относительно указания стека. 
 
     
     3.7. Порт
     
     Под портом понимают совокупность средств унифицирующих и
упрощающих  способ  взаимодействия  микропроцессора  8088   с
внешним  миром.  Порт  обеспечивает  единственную возможность
приема или передачи данных любым обьектам кроме памяти.
     Всем устройствам, с  которыми  должен  взаимодействовать
процессор,  таким  как  клавиатура,  дисководы  или  динамик,
выделяется  собственный   порт.   Порт   представляет   собой
гипотетический  путь  данных, которому присвоен номер порта и
который может принимать  или  передавать  данные  по  команде
процессора.   Когда  микропроцессор  8088  должен  передавать
данные в порт, используется команда OUT, которой  указывается
номер  порта и передаваемые данные,имеющие длину один или два
байта. Фактически команда OUT  приказывает  конкртному  порту
принять данные. Команда IN работает аналогично, только данные
считываются из порта. Микропроцессор 8088 не может определить
какие  порты  задействованы, а какие нет, так что все команды
IN и OUT выполняются вслепую.
     Операторы Бейсика обеспечивают прямой доступ  к  портам.
Операторы  Бейсика INP и OUT предоставляют те же возможности,
что и машинные команды IN и OUT. Ниже,  просто  для  примера,
приведен   фрагмент   программы   на  Бейсике,  работающей  с
динамиком:
     
     10  X=INP(97)  `чтение  порта  управления  динамиком   X
     20  REM         вероятно  будет иметь значение 76 - про-
                     верьте какое значенте Вы получите
     30  OUT 97,X+3 `установить биты управления динамиком -
                     прозвучит сигнал 
     40  OUT 97,X   `снять биты управления - окончание звука
     
     
     Порты могут использоваться в  сочетании  с  прерывниями.
Например,если  нажать  клавишу  на клавиатуре IBM/PC, никакие
данные в компьютер не передаются. Вместо  этого  генерируется
прерывание  номер 9, указывающий, что имеются данные, которые
нужно вводить с клавиатуры. В ответ на прерывание BIOS в  ПЗУ
выдаст  команду  IN  для порта клавиатуры. Только после этого
данные, определяющие какая клавиша  была  нажата,  попадут  в
компьютер.
     В случае с памятью может существовать до 1024К различных
ячеек,  причем  компьютер  не  знает,  какие  именно   адреса
действительно  имеются.  То  же  самое  касается  и  портов -
микропроцессор  8088  может  обращаться  к  порту   с   любым
допустимым номером, не зная, работает ли этот порт или нет.
     Адреса   портов   задаются   16   разрядами,   так   что
потенциально   можно   иметь   64К   различных   портов.    В
действительности   используется  гораздо  меньше  номеров  и,
следовательно,   имеются   неограниченные   возможности   для
расширения.
     Имеется   несколько   способов  использования  портов  в
IBM/PC. Первый способ - это использование  порта  просто  как
пути  данных.  Например,  коды  клавиш,  указывающие какая из
клавиш  была  нажата,  проходят  через  один  порт;   данные,
выдаваемые на устройство печати, проходят через другой порт.
     Еще  один  способ  использования  портов  заключается  в
передаче  через  них  управляющей  информации   для   внешних
устройств   и   получении  от  этих  устройств  информации  о
состоянии.  Например,  инициализация  адаптера   монохромного
дисплея  выполняется  через  порт  952.  Еще  одно назначение
портов заключается в считывании  положений  переключателей  в
системном блоке, указывающих конфигурацию системы.
     Ниже  перечисляются некоторые наиболее важные применения
портов. Как и некоторые  подробности  организации  аппаратных
средств,  описанные в главе 2, номера конкретных портов могут
не представлять  интереса  для  читателя,  но  я  привожу  их
полностью просто для полноты изложения.
     Порт 96 (шестнадцатиричное 60) используется для передачи
данных в  формате  порядковых  номеров,  от  клавиатуры.  При
описании  клавиатуры в главе 10 мы рассмотрим форматы номеров
и их использование более подробно. 
     Порт  97 (61(16)) используется для управления встроенным
динамиком, а также двигателем кассетного механизма. Он  также
позволяет  запустить аппаратный таймер, что более подробно мы
рассмотрим в главе 11.
     Порты  с  64  по  67  (40(16)-43(16))  используются  для
управления   программируемым   таймером,   используемым   как
динамиком, так и интерфейсом кассетного  накопителя.  О  том,
как используются все эти порты, будет рассказано в главе 11.
     Монохромный       дисплей      использует      несколько
последовательных портов,  начиная  с  порта  944(3В0(16)),  а
цветной  графический  -  последовательность,  начинающуюся  с
порта  976(3D0(16)).  Контролер  гибких   дисков   использует
последовательность  портов,  начиная с порта 1008(3F0(16)), а
собственно данные, записываемые на дискету или считываемые  с
нее, передаются через порт 1013(3F5(16)).
     Вместе  с  программой  3.1 для исследования конфигурации
памяти,   листинги   3.2   и   3.3   показывают    программу,
объединяющую  модули,  написанные на Паскале и на ассемблере,
которая считывает все порты и сообщает о том,  какие  из  них
наиболее  вероятно  активны.  Готовая  к  запуску версия этой
программы имеется на дискете, прилагающейся к этой  книге.  В
отличие  от  программы  обследования  памяти эта программа не
дает достаточно практичного  результата,  однако,  она  может
оказаться довольно интересной.
     Поскольку  Бейсик  обеспечивает  доступ  к  портам,  эту
программу можно было бы написать на  Бейсике,  но  тогда  для
читателя  не  было  бы  в  ней  ничего  нового.  Вместо этого
приведенный  пример  может  послужить  хорошим  введением   в
программирование    на   ассемблере,   Паскале   и   примером
объединения программ, написанных на разных языках. 
     


     Приложение   3.1.   Текст   программы   поиска
активного участка памяти (Бейсик).
     
     1000 REM
     1010 REM
     1020 REM
     1030 GOSUB 2000 ' TITLE
     1040 GOSUB 3000 ' SEARCH AND DISPLAY
     1050 GOSUB 4000 ' RETURN TO DOS
     
     2000 REM
     2010 KEY OFF : CLS : WIDTH 80
     2020 REM
     2030 PRINT "
     2040 PRINT "
     2050 PRINT
     2060 PRINT "
     2070 PRINT
     2080 PRINT "
     2090 PRINT "
     2100 PRINT
     2999 RETURN
     
     3000 REM
     3010 TRUE.% = -1
     3020 FALSE.% = 0
     3030 IN.MEMORY.% = FALSE.%
     3040 FOR PARAGRAPH.! = 0 TO 65535! STEP  64  '
CHECK EACH 1K OF MEMORY
     3050 GOSUB 5000 ' CHECK FOR ACTIVE MEMORY
     3060      IF     (IN.MEMORY.%=FALSE.%)     AND
(MEMORY.HERE.%=TRUE.%) THEN GOSUB 6000
     3070     IF      (IN.MEMORY.%=TRUE.%)      AND
(MEMORY.HERE.%=FALSE.%) THEN GOSUB 7000
     3080 IN.MEMORY.% = FALSE.%
     3090 IF MEMORY.HERE.% THEN IN.MEMORY.HERE.% =TRUE.% 
     3100 NEXT PARAGRAPH.!
     3110 IF IN.MEMORY.% THEN PARAGRAPH.! = 65536 : GOSUB 7000
     3999 RETURN
     
     4000 REM
     4010 PRINT
     4020 PRINT "Finished."
     4999 SYSTEM
     
     5000 REM
     5010 DEF SEG = PARAGRAPH.!
     5020 BYTE0.% = PEEK (0)
     5030 BYTE1.% = PEEK (1)
     5040 BYTE2.% = PEEK (2)
     5050 BYTE3.% = PEEK (3)
     5060 CHECK.COUNT.% = 0
     5070 IF BYTE0.% = 233 THEN CHECK.COUNT.% = CHECK.COUNT.% + 1
     5080 IF BYTE1.% = 233 THEN CHECK.COUNT.% = CHECK.COUNT.% + 1
     5090 IF BYTE2.% = 233 THEN CHECK.COUNT.% = CHECK.COUNT.% + 1
     5100 IF BYTE3.% = 233 THEN CHECK.COUNT.% = CHECK.COUNT.% + 1
     5110 MEMORY.HERE.% = FALSE.%
     5120 IF CHECK.COUNT.% <= 3 THEN MEMORY.HERE.% = TRUE.%
     5999 RETURN
     
     6000 REM
     6010 IN.MEMORY.% = TRUE.%
     6020 START.! = PARAGRAPH.!
     6999 RETURN
     
     7000 REM 
     7010 SIZE.! = (PARAGRAPH.!-START.!) * 16
     7020 IF SIZE.! < 8 * 1024 THEN 7999 ' 
          SUPPRESS SMALL-BLOCK FALSE REPORTS
     7030 PRINT "Active memory begins at ",
     7040 PRINT HEX$(START.!)
     7050 PRINT "                ends at ",
     7060 PRINT HEX$(PARAGRAPH.!-1);
     7070 PRINT SIZE.! / 1024;"K-bytes"; ("SIZE.!;"bytes )"
     7080 IN.MEMORY.% = FALSE.%
     7090 PRINT
     7999 RETURN
     
     9999 REM
     
     Приложение 3.2. Текст программы обработки
прерываний (Ассемблер).


beepseg segment 'code'


     assume  cs:beepseg

beep    proc   far

        cli

        mov   bx,3000
        in    al,61h
        push  ax
more:   and   al,0fch
        out   61h,al
        mov   cx,50
11:     loop  11
        or    al,2
        out   61h,al
        mov   cx,50
12:     loop  12
        dec   bx
        jnz   more
        pop   ax
        out   61h,al

        sti

        int   20h
beep    endp

beepseg  ends

end

     Приложение 3.3. Текст программы поиска активных
портов (Паскаль).
     
     
program porttest (output);

function inport (x : word) : byte;
  external;
  
var   
  count : word;
  b     : byte;
  w     : word;
  c     : array [wrd(0)..255] of word;
  headc : word;
  
procedure header1;
 var [static]
   i : integer;
 begin
   writeln;
   for i := 1 to 8 do
     write (' Port Val');
   writeln;
 end;
 
procedure header2;
 var [static]
   i : integer;
 begin
   writeln;
   for i := 1 to 8 do
     write (' Val Count');
   writeln;
 end;  
procedure initialise;
  begin
    count := 0;
    headc := 0;
    for b := 0 to 255 do
      c[b] := 0;
    for w := 1 to 25 do
      writeln;
    writeln('Program for INSIDE THE IBM PERSONAL COMPUTER');
    writeln('(C) Copyright Peter Norton, 1983');
    writeln('Listing 3.3: PORTTEST - read all ports');
    writeln;
    writeln('The following may be active ports:');
    header1;
  end;  

procedure scan_all_ports;
  begin
    for w:=0 to maxword do
      begin
        b:=inport(w);
        c[b]:=c[b]+1;
        if not(b in [wrd(0),78,110,188,202,203,207,254,255])
        then
          begin
            write(w:6,b:4);
            count:=count+1;
            headc:=headc+1;
            if headc>159 then
              begin
                headc:=0;
                header1;
              end;
          end;
      end;
    header1;
  end;
  
procedure finish_up;
  begin
    writeln;
    writeln('Here is a profile of the values returned for ',
             all of the possible ports:');
    header2;
    for b:=0 to 255 do
      write(b:4,c[b]:6);
    header2;
    writeln(count,' ports may possibly be active');
    writeln;
    writeln('Finished.')
  end;
  begin
    initialize;
    scan_all_ports;
    finish_up
  end.  
  


     Приложение 3.4. Текст программы считывания данных
из порта (Ассемблер).



inport_code segment 'code'

public  inport

inport  proc  far
        push  bp
        mov   bp,sp
        mov   dx,[bp+6]
        in    al,dx
        pop   bp
        ret   2
        
       db    '(C) Copyright Peter Norton, 1983'
       
inport  endp

inport_code ends

      end
[ Оглавление ]

Оставить комментарий

Комментарий:
можно использовать BB-коды
Максимальная длина комментария - 4000 символов.
 

Комментарии

1.
Аноним
Мне нравитсяМне не нравится
23 мая 2004, 15:58:02
Жаль, что отсутствуют рисунки... :-(

С Уважением, Рома...
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог