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

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


    Прохождения игр    
Demon's Souls |#13| Storm King
Demon's Souls |#11| Мaneater part 2
Demon's Souls |#10| Мaneater (part 1)
Demon's Souls |#9| Heart of surprises

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


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)

Реклама