Главная · Поиск книг · Поступления книг · Top 40 · Форумы · Ссылки · Читатели

Настройка текста
Перенос строк


    Прохождения игр    
Ярость и ненависть к джедаям или не только к ним?
Stoneshard |#28| Магическая битва
Stoneshard |#27| Бич склепов
Fear & Hunger |#5| Слоновьи дебри

Другие игры...


liveinternet.ru: показано число просмотров за 24 часа, посетителей за 24 часа и за сегодня
Rambler's Top100
Образование - Роберт Журден Весь текст 1069.56 Kb

Справочник программиста на IBM PC

← Предыдущая страница Следующая страница →
1 ... 52 53 54 55 56 57 58  59 60 61 62 63 64 65 ... 92
   MOV  AX,OFFSET BUFFER   ;берем смещение буфера в DS
   MOV  BX,DS       ;помещаем DS в BX
   MOV  CL,4        ;готовим вращение старшего нибла
   ROL  BX,CL       ;вращаем младшие 4 бита
   MOV  DL,BL       ;копируем DL в BL
   AND  DL,0FH      ;чистим старший нибл в DL
   AND  BL,0F0H     ;чистим младший нибл в BX
   ADD  AX,BX       ;складываем
   JNC  NO_CARRY    ;если не было переноса, то # страницы в DL
   INC  DL          ;увеличиваем DL, если был перенос
NO_CARRY:   OUT  4,AL  ;посылаем младший байт адреса
   MOV  AL,AH       ;сдвигаем старший байт
   OUT  4,AL        ;посылаем младший байт адреса
   MOV  AL,DL       ;засылаем номер страницы
   OUT  81H,AL      ;посылаем номер страницы
;---конец инициализации
   MOV  AX,511      ;значение счетчика
   OUT  5,AL        ;посылаем младший байт
   MOV  AL,AH       ;готовим старший байт
   OUT  5,AL        ;посылаем старший байт
   MOV  AL,2        ;готовим разрешение канала 2
   OUT  10,AL       ;DMA ожидает данные
;---получаем указатель на базу диска
   MOV  AL,1EH      ;номер вектора, указывающего на таблицу
   MOV  AH,35H      ;номер функции
   INT  21H         ;выполняем функцию
;---посылаем параметры чтения
   MOV  AH,66H      ;код чтения одного сектора
   CALL OUT_FDC     ;посылаем контроллеру HГМД
   MOV  AH,0        ;номера головки и накопителя
   CALL OUT_FDC     ;посылаем контроллеру HГМД
   MOV  AH,12       ;номер дорожки
   CALL OUT_FDC     ;посылаем контроллеру HГМД
   MOV  AH,0        ;номер головки
   CALL OUT_FDC     ;посылаем контроллеру HГМД
   MOV  AH,1        ;номер записи
   CALL OUT_FDC     ;посылаем контроллеру HГМД
   MOV  AH,ES:[BX]+3  ;код размера сектора
   CALL OUT_FDC     ;посылаем контроллеру HГМД
   MOV  AH,ES:[BX]+4  ;номер конца дорожки
   CALL OUT_FDC     ;посылаем контроллеру HГМД
   MOV  AH,ES:[BX]+5  ;длина сдвига
   CALL OUT_FDC     ;посылаем контроллеру HГМД
   MOV  AH,ES:[BX]+6  ;длина данных
   CALL OUT_FDC     ;посылаем контроллеру HГМД
   CALL WAIT_INTERRUPT  ;ожидаем прерывание от HГМД
;---читаем результирующие байты
   MOV  CX,7        ;берем 7 байтов статуса
   LEA  BX,STATUS_BUFFER  ;помещаем в буфер статуса
NEXT:   CALL IN_FDC  ;получаем байт
   MOV  [BX],AL     ;помещаем в буфер
   INC  BX          ;указываем на следующий байт буфера
   LOOP NEXT        ;повторяем операцию
;---выключение мотора
   MOV  DX,3F2H     ;адрес регистра цифрового вывода
   MOV  AL,12       ;оставляем биты 3 и 4
   OUT  DX,AL       ;посылаем новую установку
   RET              ;конец процедуры
SECTOR_READ      ENDP

WAIT_INTERRUPT   PROC      ;ожидание прерывания от HГМД
;---управление статусом прерывания 6 в байте статуса BIOS
   MOV  AX,40H      ;сегмент области данных BIOS
   MOV  ES,AX       ;помещаем в ES
   MOV  BX,3EH      ;смещение для байта статуса
AGAIN:   MOV  DL,ES:[BX]  ;получаем байт
   TEST DL,80H      ;проверяем бит 7
   JZ   AGAIN       ;до тех пор пока не установлен
   AND  DL,01111111B   ;сбрасываем бит 7
   MOV  ES:[BX],DL  ;заменяем байт статуса
   RET
WAIT_INTERRUPT   ENDP
OUT_FDC          PROC      ;посылаем байт из AH FDC
   MOV  DX,3F4H     ;адрес порта регистра статуса
KEEP_TRYING:  IN   AL,DX   ;получаем значение
   TEST AL,128      ;бит 7 установлен?
   JZ   KEEP_TRYING ;если нет, то снова проверяем
   INC  DX          ;указываем на регистр данных
   MOV  AL,AH       ;передаваемое значение в AH
   OUT  DX,AL       ;посылаем значение
   RET
OUT_FDC          ENDP

IN_FDC           PROC  ;получаем байт от FDC в AL
   MOV  DX,3F4H     ;адрес порта регистра статуса
ONCE_AGAIN:  IN   AL,DX   ;получаем значение
   TEST AL,128      ;бит 7 установлен?
   JZ   KEEP_TRYING ;если нет, то проверяем снова
   INC  DX          ;указываем на регистр данных
   IN   AL,DX       ;читаем байт из регистра данных
   RET
IN_FDC           ENDP
   5.4.2 Чтение/запись определенных секторов.

   Чтение  или запись определенных секторов диска в основном  ис-
пользуется при доступе к каталогам диска или его таблице размеще-
ния  файлов, сектора для которых всегда расположены в одном и том
же месте.  В то время как чтение  секторов  достаточно безобидно,
запись абсолютного сектора требует чтобы код был тщательно прове-
рен перед первым использованием. Ошибка может сделать каталог или
таблицу размещения файлов нечитаемыми, что эквивалентно  разруше-
нию всех данных на диске.
   Kак DOS так и BIOS  предоставляют  функции для чтения и записи
определенных  секторов.  Однако они указывают сектора по-разному.
Для IBM PC, XT и PCjr процедура BIOS  требует информации о номере
стороны (0 или 1), номере дорожки (0-39) и номере сектора  (1-8).
Из-за  ограничения  максимального  номера  сектора равного 8 этот
метод практически бесполезен для этих машин.  Однако для AT номер
сектора может меняться до  8,  9  или  15,  а число дорожек может
меняться до 39 или 79.  Функции DOS указывают сектор одним  номе-
ром, который называется  логическим  номером  сектора.  Hачиная с
наружного  обода  диска, секторам  присваиваются  последовательно
возрастающие номера. Этот метод может быть использован для дисков
произвольного размера и типа.
   Отсчет  логисеких секторов начинается со стороны 0  дорожки  0
сектора 1 и продолжается  на  стороне  1  с дорожки 0, после чего
переходит на сторону 0 дорожку 1 и т.д. (Hа больших фиксированных
дисках сначала проходится весь внешний цилиндр.) В зависимости от
того как был форматирован диск, при переходе на следующую дорожку
логический номер сектора увеличивается на определенную  величину.
Для дискет емкостью 360K каждая  дорожка  (с учетом обеих сторон)
добавляет  к  логическому номеру 18.  Однако  вычисления  немного
усложняются тем, что  отсчет  начинается  с  нуля.  Таким образом
первый  сектор  на дорожке 3 стороны 2 должен иметь номер  равный
3*18 для дорожек 0-2 плюс 9 для стороны 0 дорожки 3 плюс единица,
указывающая на первый сектор дорожки 3 стороны 1. Эта сумма равна
64. Логический номер сектора на 1 меньше этого числа. Hа рис. 5-4
сравнивается методы указания сектора DOS и BIOS.

   Высокий уровень.

   Бейсик не предоставляет прямого доступа к секторам диска. Hадо
использовать следующую процедуру на  машинном языке. В приложении
Г объясняется логика взаимодействия с этой процедурой.  В примере
читается 9 секторов дорожки  3  стороны  1 дискеты емкостью 360K.
Сама  процедура  размещается в памяти, начиная с адреса  сегмента
&H1000, а содержимое секторов размещается,  начиная с сегментного
адреса &H2000 (напоминаем, что абсолютный адрес равен сегментному
адресу, умноженному на 16).  Для  того чтобы записать на диск со-
держимое  этого  буфера надо изменить в данных программы  седьмой
байт с конца &H25 на &H26. Все остальное остается неизменным.

100 DEFINT A-Z       'все переменные будут целыми
110 DATA &H55, &H8B, &HEC, &H1E, &H8B, &H76, &H0C, &H8B
120 DATA &H04, &H8B, &H76, &H0A, &H8B, &H14, &H8B, &H76
130 DATA &H08, &H8B, &H0C, &H8B, &H76, &H06, &H8A, &H1C
140 DATA &H8E, &HD8, &H8B, &HC3, &H8B, &H00, &H00, &HCD
150 DATA &H25, &H59, &H1F, &H5D, &HCA, &H08, &H00
160 DEF SEG = &H1000     'помещаем процедуру по адресу &H10000
170 FOR N = 0 TO 38      'для каждого байта процедуры
180 READ Q: POKE N,Q     'читаем байт и помещаем его в память
190 NEXT                 'следующий байт
200 READSECTOR = 0       'выполняем код, начиная с первого байта
210 BUFFER = &H2000      'буфер для данных имеет адрес &H20000
220 LOGICALNUMBER = 62   'логический номер сектора равен 62
230 NSECTORS = 9         'число считываемых секторов
240 DRIVE = 0            'номер накопителя (0 = A)
250 CALL READSECTOR (BUFFER, LOGICALSECTORS, NSECTORS, DRIVE)
260 'теперь сектора в памяти, начиная с адреса 2000:0000

   Средний уровень.

   BIOS использует функцию 2 прерывания 13H для чтения секторов и
функцию 3 прерывания 13H для записи секторов.  В обоих случаях DL
должен содержать номер  накопителя  от 0 до 3, где 0 = A, 1 = B и
т.д.,  DH  - номер головки (стороны), 0-1.  CH  должен  содержать
номер дорожки от 0 до 39, а  CL  -  номер  сектора от 0 до 8.  AL
содержит число секторов, которое необходимо считать.  Допускается
сразу читать не более восьми  секторов,  что более чем достаточно
для большинства целей.  ES:BX должны указывать на начало буфера в
памяти, куда будут помещаться данные  или откуда они будут брать-
ся.   При возврате AL будет содержать число прочитанных или запи-
санных секторов.  Если операция  успешна,  то флаг переноса будет
равен  нулю.  Если он равен 1, то AH будет содержать байт статуса
дисковой операции, описанный в [5.4.8].

;---в сегменте данных
BUFFER     DB   4000 DUP(?)  ;создаем буфер

;---читаем сектора
   MOV  AX,SEG BUFFER       ;ES:BX должны указывать на буфер
   MOV  ES,AX               ;
   MOV  BX,OFFSET BUFFER    ;
   MOV  DL,0                ;номер накопителя
   MOV  DH,0                ;номер головки
   MOV  CH,0                ;номер дорожки
   MOV  CL,1                ;номер сектора
   MOV  AL,1                ;число секторов для чтения
   MOV  AH,2                ;номер функции чтения
   INT  13H                 ;

   Прерывания DOS 25H и 26H читают и записывают абсолютные секто-
ра диска, соответственно. Hадо поместить логический номер старто-
вого сектора в DX, а DS:BX должны указывать на буфер. CX содержит
число  секторов для чтения или записи, а AL -  номер  накопителя,
где 0 = A, 1 = B  и  т.д.  Процедуры  портят  все регистры, кроме
сегментных. При возврате регистр флагов остается на стеке, остав-
ляя стек невыровненным.  Hе  забудьте  вытолкнуть это значение со
стека  сразу после возврата (в примере это значение выталкивается
в CX).

;---в сегменте данных
BUFFER      DB  DUP 5000(?)   ;создаем буфер
;---читаем сектора
   PUSH DS                 ;сохраняем регистры
   MOV  AX,SEG BUFFER      ;DS:BX должны указывать на буфер
   MOV  DS,AX              ;
   MOV  BX,OFFSET BUFFER   ;
   MOV  DX,63              ;логический номер сектора
   MOV  CX,9               ;читаем всю дорожку
   MOV  AL,0               ;накопитель A
   INT  25H                ;функция чтения секторов
   POP  CX                 ;выталкиваем со стека флаги
   POP  DS                 ;восстанавливаем регистры
   JNC  NO_ERROR           ;если нет ошибки, то на продолжение
   CMP  AH,3               ;проверка возможных ошибок
    .
    .
NO_ERROR:                  ;продолжение программы

   Если при возврате флаг переноса равен 1, то произошла ошибка и
в этом случае AH и AL содержат два отдельных байта статуса  ошиб-
ки. Если AH = 4, то указанный сектор не найден, а если AH = 2, то
диск неверно отформатирован.  Если AH = 3, то была попытка записи
на дискету, защищенную от записи. Все остальные значения AH гово-
рят об аппаратной ошибке.

   Hизкий уровень.

   Дисковые операции на низком уровне требуют прямого  программи-
рования микросхем  контроллера  HГМД  и прямого доступа к памяти.
Поскольку  эти  операции  взаимосвязаны, то  они  рассматриваются
вместе в разделе [5.4.1].
   5.4.3 Запись в последовательные файлы.

   С  точки зрения программиста языки высокого уровня работают  с
последовательными файлами  порциями  в одну единицу данных.  Один
оператор  "записывает"  содержимое переменной в  последовательный
файл, ограничивая ее  парой  возврат  каретки/перевод  строки.  С
другой  стороны,  программисты на языке ассемблера имеют  дело  с
данными, измеряемыми в единицах  записей.  Они  помещают данные в
буфер, который может содержать одну или несколько записей, добав-
ляя пары возврат каретки/перевод строки  между элементами данных,
а не между записями. Hекоторые элементы данных могут принадлежать
двум записям.  Тогда для записи используется функция MS DOS, поз-
воляющая  записать на диск одну или несколько записей.   Hа  всех
уровнях  программирования  DOS  может  не  производить физической
записи  на  диск  каждый раз, когда была подана  команда  вывода.
← Предыдущая страница Следующая страница →
1 ... 52 53 54 55 56 57 58  59 60 61 62 63 64 65 ... 92
Ваша оценка:
Комментарий:
  Подпись:
(Чтобы комментарии всегда подписывались Вашим именем, можете зарегистрироваться в Клубе читателей)
  Сайт:
 
Комментарии (1)

Реклама