.context h.default
.context h.contents
.context sysp
.context @L8000
:l15
:nБиблиотека системного программиста
┌──────────────────────────────────────────────────────────────────┐
│Библиотека системного программиста                                │
│Справочная база данных, (C)Фролов А.В., Фролов Г.В., V1.0, 1991   │
└──────────────────────────────────────────────────────────────────┘
 
\a\b Том 1, книга 1,2 (векторная таблица связи, драйверы)\vsysp11\v\p
\a\b Том 1, книга 3 (дисковая подсистема)\vsysp13\v\p
\a\b Том 2, (аппаратное обеспечение IBM PC/XT/AT)\vsysp2\v\p
\a\b Том 3, (адаптеры CGA/EGA/VGA)\vsysp3\v\p
\a\b Том 4, (инструментальные средства)\vsysp4\v\p
\a\b Другие тома\vsysp5x\v\p
 
.context sysp11
.context @L8001
:l15
:nОписание функций
   Библиотека системного программиста, том1, книга 1, 2. \a< Оглавление >\vsysp\v
───────────────────────────────────────────────────────────────────────────────────
Макро для составления FAR-указателя                         \a FP_MAKE\vfp_make\v
Получить адрес векторной таблицы связи                      \a get_cvt\vget_cvt\v
Получить адрес DDCB заданного диска                         \a get_ddcb\vget_ddcb\v
Прочитать заголовок EXE-файла                               \a get_exeh\vget_exeh\v
Получить адрес первого DDCB                                 \a get_fddcb\vget_fddcb\v
Получить адрес первой DTF                                   \a get_fdft\vget_fdft\v
Получить адрес первого MCB                                  \a get_fmcb\vget_fmcb\v
Получить адрес векторной таблицы связи                      \a get_mcvt\vget_mcvt\v
Получить адрес следующего DDCB                              \a get_nddcb\vget_nddcb\v
Получить адрес следующей DTF                                \a get_ndft\vget_ndft\v
Получить адрес следующего MCB                               \a get_nmcb\vget_nmcb\v
Получить справку по заданному контексту                     \a help\vhelp\v
 
───────────────────────────────────────────────────────────────────────────────
.context FP_MAKE
.context @L8002
:l15
:nФункция FP_MAKE
\a\u< Назад >\vsysp11\v \a< Оглавление >\vsysp\v \a< Пример >\vshow_psp.c\v\p
─────────────────────────────────────────────────────────────────────────────────────
 
\bПрототип функции:\p
          FP_MAKE(seg,off)
 
\bПараметры функции:\p
             seg - сегмент;
             off - смещение
 
\bОписание функции:\p
          Макро составляет FAR-указатель, пользуясь
          значениями сегмента и смещения
 
\bВозвращаемое значение:\p
          FAR-указатель seg:off
 
 
 ─────────────────────────────────────────────────────────────────────────────────────
.context get_cvt
.context @L8003
:l15
:nФункция get_cvt
\a\u< Назад >\vsysp11\v \a< Оглавление >\vsysp\v \a< Пример >\vshow_cvt.c\v\p
─────────────────────────────────────────────────────────────────────────────────────
 
\bПрототип функции:\p
          void far *get_cvt(void);
 
\bПараметры функции:\p
          Нет
 
\bОписание функции:\p
          Функция возвращает адрес векторной таблицы связи
          для DOS версий 2.х, 3.х, 4.00, 4.01
 
\bВозвращаемое значение:\p
          Указатель на векторную таблицу связи
 
 
 ─────────────────────────────────────────────────────────────────────────────────────
.context get_ddcb
.context @L8004
:l15
:nФункция get_ddcb
\a\u< Назад >\vsysp11\v \a< Оглавление >\vsysp\v \a< Пример >\vshowddcb.c\v\p
─────────────────────────────────────────────────────────────────────────────────────
 
\bПрототип функции:\p
          DDCB far *get_ddcb(int device_number)
 
\bПараметры функции:\p
          device_number - номер диска, для которого
                          требуется получить DDCB
                          Номер задается так:
                          0 - текущий диск, 1 - В и т.д.
 
\bОписание функции:\p
          Функция возвращает адрес блока управления
          устройством DOS DDCB
 
\bВозвращаемое значение:\p
          Указатель на DDCB заданного диска
 
 
 ─────────────────────────────────────────────────────────────────────────────────────
.context get_exeh
.context @L8005
:l15
:nФункция get_exeh
\a\u< Назад >\vsysp11\v \a< Оглавление >\vsysp\v \a< Пример >\vshow_exe.c\v\p
─────────────────────────────────────────────────────────────────────────────────────
 
\bПрототип функции:\p
          int get_exeh(EXE_HDR *exeh,RELOC_TAB **rtb,FILE *exe_file)
 
\bПараметры функции:\p
             exeh -  указатель на структуру, которая
                     должна быть заполнена информацией
                     из заголовка EXE-файла
 
             rtb  -  указатель на указатель на таблицу
                     размещений сегментов программы
 
             exe_file - указатель на открытый EXE-файл
                     (до вызова функции нельзя обращаться
                     к этому файлу, т.к. считается, что
                     указатель текущего смещения установлен
                     на начало файла)
 
\bОписание функции:\p
          Функция читает заголовок EXE-файла в
          структуру типа EXE_HDR, заказывает память
          для таблицы размещений сегментов и считывает
          таблицу в эту область. Адрес заказанной области
          помещается по адресу, передаваемому в rtb.
          Если таблица размещений отсутствует, память для
          нее не заказывается.
 
\bВозвращаемое значение:\p
          0 при успешном считывании заголовка;
          -1 в случае неправильного формата заголовка
 
 
 ─────────────────────────────────────────────────────────────────────────────────────
.context get_fddcb
.context @L8006
:l15
:nФункция get_fddcb
\a\u< Назад >\vsysp11\v \a< Оглавление >\vsysp\v \a< Пример >\vshow_ddc.c\v\p
─────────────────────────────────────────────────────────────────────────────────────
 
\bПрототип функции:\p
          DDCB far *get_fddcb(CVT far *cvt)
 
\bПараметры функции:\p
              cvt - адрес вектрной таблицы связи
 
\bОписание функции:\p
          Функция возвращает адрес первого блока DDCB
 
\bВозвращаемое значение:\p
          Указатель на первый блок DDCB
 
 
 ─────────────────────────────────────────────────────────────────────────────────────
.context get_fdft
.context @L8007
:l15
:nФункция get_fdft
\a\u< Назад >\vsysp11\v \a< Оглавление >\vsysp\v \a< Пример >\vshow_dfc.c\v\p
─────────────────────────────────────────────────────────────────────────────────────
 
\bПрототип функции:\p
          DTF far *get_fdtf(CVT far *cvt)
 
\bПараметры функции:\p
              cvt - адрес векторной таблицы связи
 
\bОписание функции:\p
          Функция возвращает адрес первой таблицы файлов DOS
 
\bВозвращаемое значение:\p
          Указатель на первый блок DDCB
 
 
 ─────────────────────────────────────────────────────────────────────────────────────
.context get_fmcb
.context @L8008
:l15
:nФункция get_fmcb
\a\u< Назад >\vsysp11\v \a< Оглавление >\vsysp\v \a< Пример >\vshow_mcb.c\v\p
─────────────────────────────────────────────────────────────────────────────────────
 
\bПрототип функции:\p
          MCB far *get_fmcb(CVT far *cvt)
 
\bПараметры функции:\p
             cvt - адрес векторной таблицы связи
 
\bОписание функции:\p
          Функция возвращает адрес первого блока MCB
 
\bВозвращаемое значение:\p
          Указатель на первый блок MCB
 
 
 ─────────────────────────────────────────────────────────────────────────────────────
.context get_mcvt
.context @L8009
:l15
:nФункция get_mcvt
\a\u< Назад >\vsysp11\v \a< Оглавление >\vsysp\v \a< Пример >\vshow_ddc.c\v\p
─────────────────────────────────────────────────────────────────────────────────────
 
\bПрототип функции:\p
          CVT far *get_mcvt(void);
 
\bПараметры функции:\p
          Нет
 
\bОписание функции:\p
          Функция возвращает адрес векторной таблицы связи
          для DOS версий 2.х, 3.х, 4.00, 4.01
 
\bВозвращаемое значение:\p
          Указатель на векторную таблицу связи
 
 
 ─────────────────────────────────────────────────────────────────────────────────────
.context get_nddcb
.context @L800a
:l15
:nФункция get_nddcb
\a\u< Назад >\vsysp11\v \a< Оглавление >\vsysp\v \a< Пример >\vshow_ddc.c\v\p
─────────────────────────────────────────────────────────────────────────────────────
 
\bПрототип функции:\p
          DDCB far *get_nddcb(DDCB far *ddcb);
 
\bПараметры функции:\p
             ddcb - адрес предыдущего DDCB
 
\bОписание функции:\p
          Функция возвращает адрес следующего блока DDCB
          или 0, если это последний блок в цепочке
 
\bВозвращаемое значение:\p
          Указатель на следующий блок DDCB
          или 0, если это последний блок в цепочке
 
 
 ─────────────────────────────────────────────────────────────────────────────────────
.context get_ndft
.context @L800b
:l15
:nФункция get_ndft
\a\u< Назад >\vsysp11\v \a< Оглавление >\vsysp\v \a< Пример >\vshow_dfc.c\v\p
─────────────────────────────────────────────────────────────────────────────────────
 
\bПрототип функции:\p
          DFT far *get_ndft(DFT far *dft)
 
\bПараметры функции:\p
             dft - адрес предыдущей таблицы DFT
 
\bОписание функции:\p
          Функция возвращает адрес следующей
          таблицы файлов DOS или 0, если это последняя таблица
 
\bВозвращаемое значение:\p
          Указатель на следующую DFT, или 0, если последняя
 
 
 ─────────────────────────────────────────────────────────────────────────────────────
.context get_nmcb
.context @L800c
:l15
:nФункция get_nmcb
\a\u< Назад >\vsysp11\v \a< Оглавление >\vsysp\v \a< Пример >\vshow_mcb.c\v\p
─────────────────────────────────────────────────────────────────────────────────────
 
\bПрототип функции:\p
          MCB far *get_fmcb(MCB far *mcb)
 
\bПараметры функции:\p
             mcb - адрес предыдущего MCB
 
\bОписание функции:\p
          Функция возвращает адрес следующего блока MCB
          или 0, если это последний блок. В качестве
          параметра используется указатель на предыдущий
          блок MCB
 
\bВозвращаемое значение:\p
          Указатель на следующий блок MCB или 0, если
          это последний MCB
 
 
 ─────────────────────────────────────────────────────────────────────────────────────
.context help
.context @L800d
:l15
:nФункция help
\a\u< Назад >\vsysp11\v \a< Оглавление >\vsysp\v \a< Пример >\vqhrun.c\v\p
─────────────────────────────────────────────────────────────────────────────────────
 
\bПрототип функции:\p
          int help(char *help_file, char *help_topic);
 
\bПараметры функции:\p
             help_file  - переменная среды, указывающая
                          на путь к справочной базе
 
             help_topic - контекст для поиска в базе
 
 
\bОписание функции:\p
          Функция получает в качестве параметров
          переменную среды, указывающую на путь
          к справочной базе данных и указатель
          на строку контекста для поиска в базе.
          Затем запускается как дочерний процесс
          утилита Microsoft Quick Help QH.EXE, для
          которой формируются среда и параметры.
 
\bВозвращаемое значение:\p
          0 при успешном запуске процесса
          -1 не удалось запустить процесс
 
 
 ─────────────────────────────────────────────────────────────────────────────────────
.context show_psp.c
.context @L800e
\a\u< Назад >\vsysp11\v \a< Оглавление >\vsysp\v\p
───────────────────────────────────────────────────────────────────────────────────
#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#include "sysp.h"
 
void main(void);
 
void main(void) {
 
  PSP far *psp_ptr;
 
 
  psp_ptr = FP_MAKE(_psp,0);  // Конструируем указатель
                              //  на PSP
  printf("PSP расположено по адресу:   %Fp\\n"
         "Доступно памяти, байт:       %ld\\n"
         "PSP родительской программы:  %Fp\\n"
         "\\n",
         psp_ptr,
         (long)(psp_ptr->mem_top)*16L,
         FP_MAKE(psp_ptr->parn_psp,0));
  exit(0);
 
}
───────────────────────────────────────────────────────────────────────────────────
.context show_cvt.c
.context @L800f
\a\u< Назад >\vsysp11\v \a< Оглавление >\vsysp\v\p
───────────────────────────────────────────────────────────────────────────────────
#include <dos.h>
#include <stdio.h>
#include "sysp.h"
 
void main(void);
 
void main(void)
{
    void far *cvt;
 
    cvt=get_cvt();
    printf("Адрес векторной таблицы связи: %Fp\\n",cvt);
 
    exit(0);
}
───────────────────────────────────────────────────────────────────────────────────
.context showddcb.c
.context @L8010
\a\u< Назад >\vsysp11\v \a< Оглавление >\vsysp\v\p
───────────────────────────────────────────────────────────────────────────────────
#include <dos.h>
#include <stdio.h>
#include <stdlib.h>
#include "sysp.h"
 
void main(void);
 
void main(void)
{
    DDCB far *ddcb;
    unsigned char dr;
 
    for(dr=1;;dr++) {
 
      ddcb=get_ddcb(dr);
      if(ddcb == (DDCB far *)0) break;
      printf("%Fp\\n",ddcb);
    }
    exit(0);
}
───────────────────────────────────────────────────────────────────────────────────
.context show_exe.c
.context @L8011
\a\u< Назад >\vsysp11\v \a< Оглавление >\vsysp\v\p
───────────────────────────────────────────────────────────────────────────────────
#include <stdio.h>
#include <stdlib.h>
#include "sysp.h"
 
void main(int, char *[]);
 
void main(int argc, char *argv[]) {
 
   printf("Распечатка заголовка EXE-файла\\n"
          "Copyright (C)Frolov A., 1990\\n\\n");
 
   if( argc != 2 ) {
      printf( "  Задайте путь EXE-файла в качестве параметра\\n" );
      exit(0);
   }
 
   if( gethdr( argv[1]) != 0) {
         printf( "Ошибка в формате файла или нет такого файла\\n" );
         exit(0);
   }
   exit(0);
}
 
int gethdr( char *path) {
 
   EXE_HDR     header;
   RELOC_TAB   *reloc;
   FILE        *inpfile;
   int         i;
 
   if((inpfile = fopen(path,"rb")) == 0) return(-1);
 
   if(get_exeh(&header,&reloc,inpfile) != 0) {
      fclose(inpfile);
      return(-1);
   }
   printf("Магическое число:                    %04X\\n"
          "Длина последней страницы файла:      %d\\n"
          "Количество страниц в файле:          %d\\n"
          "Кол. элементов табл. перемещений:    %d\\n"
          "Размер заголовка в параграфах:       %d\\n"
          "Минимальная память для программы:    %04X\\n"
          "Максимальная память для программы:   %04X\\n"
          "Значение адреса стека SS:SP:         %04X:%04X\\n"
          "Контрольная сумма:                   %04X\\n"
          "Значения для регистров CS:IP:        %04X:%04X\\n"
          "Смещение табл. перемещений:          %02X\\n"
          "Номер оверлея:                       %d\\n",
          header.signature,
          header.part_pag,
          header.file_size,
          header.rel_item,
          header.hdr_size,
          header.min_mem,
          header.max_mem,
          header.ss_reg,
          header.sp_reg,
          header.chk_summ,
          header.cs_reg,
          header.ip_reg,
          header.relt_off,
          header.overlay);
 
 
   if(reloc != 0) {
      printf("\\nСодержимое таблицы перемещений:\\n\\n");
 
      for(i=0;i < header.rel_item; i++) {
         printf("%04X:%04X\\n",
         (reloc+i)->segment,
         (reloc+i)->offset);
 
      }
      free(reloc);
   }
   fclose(inpfile);
   return(0);
}
───────────────────────────────────────────────────────────────────────────────────
.context show_ddc.c
.context @L8012
\a\u< Назад >\vsysp11\v \a< Оглавление >\vsysp\v\p
───────────────────────────────────────────────────────────────────────────────────
#include <dos.h>
#include <stdio.h>
#include <stdlib.h>
#include "sysp.h"
 
void main(void);
 
void main(void)
{
    CVT far *cvt;
    DDCB far *ddcb;
 
    printf("\\nБлоки управления дисковыми устройствами (DDCB)"
           "\\nCopyright (C)Frolov A., 1990\\n"
           "\\n");
 
    cvt=get_mcvt();
 
    ddcb=get_fddcb(cvt);
 
    for(;;) {
 
      if(ddcb == (DDCB far *)0) break;
 
      printf("Адрес DDCB:                          %Fp\\n"
             "Номер устройства:                    %d\\n"
             "Дополнительный номер:                %d\\n"
             "Размер сектора:                      %d\\n"
             "Размер кластера в секторах:          %d\\n"
             "База размера кластера:               %d\\n"
             "Зарезервировано секторов:            %d\\n"
             "Число копий FAT:                     %d\\n"
             "Макс. файлов в корневом каталоге :   %d\\n"
             "Первый кластер данных:               %d\\n"
             "Всего кластеров:                     %d\\n"
             "Размер FAT в секторах:               %d\\n"
             "Первый сектор корневого каталога:    %d\\n"
             "Поле reserv1:                        %01X\\n"
             "Адрес драйвера:                      %Fp\\n"
             "Байт описателя среды носителя:       %01X\\n"
             "Флаг доступа:                        %01X\\n"
             "Адрес следующего DDCB:               %Fp\\n"
             "Поле reserv2:                        %04X\\n"
             "Блок построен:                       %04X\\n"
             "----------------------------------------------------\\n\\n",
             ddcb,
             ddcb->drv_num,
             ddcb->drv_numd,
             ddcb->sec_size,
             ddcb->clu_size,
             ddcb->clu_base,
             ddcb->boot_siz,
             ddcb->fat_num,
             ddcb->max_dir,
             ddcb->data_sec,
             ddcb->hi_clust,
             ddcb->fat_size,
             ddcb->root_sec,
             ddcb->reserv1,
             ddcb->drv_addr,
             ddcb->media,
             ddcb->acc_flag,
             ddcb->next,
             ddcb->reserv2,
             ddcb->built);
 
      ddcb=get_nddcb(ddcb);
 
    }
 
    exit(0);
}
───────────────────────────────────────────────────────────────────────────────────
.context show_dfc.c
.context @L8013
\a\u< Назад >\vsysp11\v \a< Оглавление >\vsysp\v\p
───────────────────────────────────────────────────────────────────────────────────
#include <dos.h>
#include <stdio.h>
#include <stdlib.h>
#include "sysp.h"
 
void main(void);
 
void main(void)
{
 
    CVT far *cvt;
    DFT far *dft;
    unsigned i,j,k;
    DFCB far *dfcb;
    FILE *list;
 
    printf("Информация об открытых файлах DOS\\n"
           "Copyright Frolov A. (C),1990\\n");
 
    // Открываем файл для вывода информации о файлах
 
    list=fopen("!dfcb.lst","w+");
 
    fprintf(list,"Информация об открытых файлах DOS\\n"
           "Copyright Frolov A. (C),1990\\n\\n");
 
    cvt=get_mcvt();     // Адрес векторной таблицы связи
    dft=get_fdft(cvt);  // Адрес начала таблицы файлов
 
    for(;;) {
      if(dft == (DDCB far *)0) break;  // Конец таблицы файлов
 
      i=dft->file_count;
      fprintf(list,"Таблица файлов DFT: %Fp, в ней %d файлов\\n"
                   "===========================================\\n",
                   dft,i);
 
      for(j=0;j<i;j++) {   // Цикл по файловым управляющим блокам
 
         dfcb=(&(dft->dfcb))+j; // Адрес DFCB файла
 
         fprintf(list,"\\nDFCB файла: %Fp\\n\\n",dfcb);
 
         fprintf(list,"Имя файла: ");
         for(k=0;k<11;k++) {
            fputc(dfcb->filename[k],list);
         }
 
         fprintf(list,"\\nКоличество file handles:       %d\\n"
                "Режим доступа:                 %d\\n"
                "Поле reserv1:                  %04X\\n"
                "Информация об устройстве:      %04X\\n"
                "Адрес драйвера:                %Fp\\n"
                "Начальный кластер:             %d\\n"
                "Время:                         %04X\\n"
                "Дата:                          %04X\\n"
                "Размер файла в байтах:         %ld\\n"
                "Текущее смещение в файле:      %ld\\n"
                "Поле reserv2:                  %04X\\n"
                "Последний прочитанный кластер: %d\\n"
                "Сегмент PSP владельца файла:   %04X\\n"
                "Поле reserv7:                  %d\\n"
                "--------------------------------------\\n\\n",
                dfcb->handl_num,
                dfcb->access_mode,
                dfcb->reserv1,
                dfcb->dev_info,
                dfcb->driver,
                dfcb->first_clu,
                dfcb->time,
                dfcb->date,
                dfcb->fl_size,
                dfcb->offset,
                dfcb->reserv2,
                dfcb->last_clu,
                dfcb->ownr_psp,
                dfcb->reserv7);
 
      }
      dft=get_ndft(dft);
    }
    fclose(list);
    exit(0);
}
───────────────────────────────────────────────────────────────────────────────────
.context show_mcb.c
.context @L8014
\a\u< Назад >\vsysp11\v \a< Оглавление >\vsysp\v\p
───────────────────────────────────────────────────────────────────────────────────
#include <dos.h>
#include <stdio.h>
#include "sysp.h"
 
void main(void);
 
void main(void)
{
    CVT far *cvt;
    MCB far *mcb;
 
    printf("\\nБлоки управления памятью (MCB)"
           "\\nCopyright (C)Frolov A., 1990\\n"
           "\\nАдрес MCB Тип Владелец Размер"
           "\\n--------- --- -------- ------"
           "\\n");
    cvt=get_mcvt();
    mcb=get_fmcb(cvt);
    for(;;) {
 
      if(mcb == (MCB far *)0) break;
      printf("%Fp %c   %04X     %04X\\n",
         mcb,
         mcb->type,
         mcb->owner,
         mcb->size);
      mcb=get_nmcb(mcb);
 
    }
    exit(0);
}
───────────────────────────────────────────────────────────────────────────────────
.context qhrun.c
.context @L8015
\a\u< Назад >\vsysp11\v \a< Оглавление >\vsysp\v\p
───────────────────────────────────────────────────────────────────────────────────
#include <stdio.h>
#include <conio.h>
#include <process.h>
 
main()
{
    int r;
 
    // Получаем справку о функции printf,
    //  справочная база данных расположена
    //  в каталоге d:\\qc2\\bin
 
    r = help("HELPFILES=d:\\\\qc2\\\\bin;","printf");
 
    if( r == -1 )
        printf( "Невозможно запустить процесс" );
    else
        printf( "\\nПроцесс завершен" );
    exit(r);
}
 
───────────────────────────────────────────────────────────────────────────────────
.context sysp13
.context @L8016
:l15
:nОписание функций
   Библиотека системного программиста, том1, книга 3. \a< Оглавление >\vsysp\v
───────────────────────────────────────────────────────────────────────────────────
Определить конфигурацию дисковой подсистемы                 \a disk_cfg\vdisk_cfg\v
Выбрать элемент из FAT                                      \a fat\vfat\v
Получить информацию об устройстве                           \a get_devi\vget_devi\v
Вычислить адрес таблицы параметров дискеты                  \a get_dpt\vget_dpt\v
Вычислить адрес таблицы параметров диска 1                  \a get_hdp1\vget_hdp1\v
Вычислить адрес таблицы параметров диска 2                  \a get_hdp2\vget_hdp2\v
Получить адрес идентификатора BIOS                          \a getbiosi\vgetbiosi\v
Считать загрузочную запись                                  \a getboot\vgetboot\v
Считать главную загрузочную запись                          \a getmboot\vgetmboot\v
Проверить условие "Конец файла"                             \a heof\vheof\v
Определить модель компьютера                                \a pc_model\vpc_model\v
 
───────────────────────────────────────────────────────────────────────────────
.context disk_cfg
.context @L8017
:l15
:nФункция disk_cfg
\a\u< Назад >\vsysp13\v \a< Оглавление >\vsysp\v \a< Пример >\vdiscshow.c\v\p
─────────────────────────────────────────────────────────────────────────────────────
 
\bПрототип функции:\p
          void disk_cfg(DISK_CONFIG* cfg);
 
\bПараметры функции:\p
              DISK_CONFIG* cfg - указатель на заполняемую
                                 структуру
 
\bОписание функции:\p
          Функция заполняет структуру, описывающую
          конфигурацию дисковой подсистемы:
 
             typedef struct _DISK_CONFIG_ {
                int  n_floppy;
                int  n_hard;
                int  t_floppy1;
                int  t_floppy2;
                int  t_hard1;
                int  t_hard2;
             } DISK_CONFIG;
 
\bВозвращаемое значение:\p
          Ничего
 
 
 ─────────────────────────────────────────────────────────────────────────────────────
.context fat
.context @L8018
:l15
:nФункция fat
\a\u< Назад >\vsysp13\v \a< Оглавление >\vsysp\v \a< Пример >\vdirlist.c\v\p
─────────────────────────────────────────────────────────────────────────────────────
 
\bПрототип функции:\p
          int fat(b_fat, t_fat, idx);
 
\bПараметры функции:\p
          char _far *b_fat  - буфер, содержащий FAT
 
          int t_fat         - формат FAT, может быть
                              равен 12 или 16
 
          int idx           - номер элемента FAT, который
                              должен быть выбран
 
\bОписание функции:\p
          Функция выбирает элемент с заданным номером из таблицы
          размещения файлов FAT. Формат FAT передается
          функции как параметр.
 
\bВозвращаемое значение:\p
          Содержимое ячейки FAT с указанным номером
 
 
 ─────────────────────────────────────────────────────────────────────────────────────
.context get_devi
.context @L8019
:l15
:nФункция get_devi
\a\u< Назад >\vsysp13\v \a< Оглавление >\vsysp\v \a< Пример >\vshow_di.c\v\p
─────────────────────────────────────────────────────────────────────────────────────
 
\bПрототип функции:\p
          int get_devi(int handle, int *info);
 
\bПараметры функции:\p
          handle      - файловый номер (хендл) для
                        которого необходимо получить
                        информцию
 
          info        - указатель на слово, в которое
                        должна быть записана информация
 
\bОписание функции:\p
          Функция получает информацию о файле
          или об устройстве по его файловому номеру.
 
 
\bВозвращаемое значение:\p
          0          - если нет ошибок;
          Код ошибки - если произошла ошибка.
 
 
 ─────────────────────────────────────────────────────────────────────────────────────
.context get_dpt
.context @L801a
:l15
:nФункция get_dpt
\a\u< Назад >\vsysp13\v \a< Оглавление >\vsysp\v \a< Пример >\vdiscshow.c\v\p
─────────────────────────────────────────────────────────────────────────────────────
 
\bПрототип функции:\p
          DPT _far *get_dpt(void);
 
\bПараметры функции:\p
          Нет
 
\bОписание функции:\p
          Функция возвращает указатель на таблицу
          параметров дискеты
 
\bВозвращаемое значение:\p
          Указатель на таблицу параметров дискеты DPT
 
 
 ─────────────────────────────────────────────────────────────────────────────────────
.context get_hdp1
.context @L801b
:l15
:nФункция get_hdp1
\a\u< Назад >\vsysp13\v \a< Оглавление >\vsysp\v \a< Пример >\vdiscshow.c\v\p
─────────────────────────────────────────────────────────────────────────────────────
 
\bПрототип функции:\p
          HDPT _far *get_hdp1(void);
 
\bПараметры функции:\p
          Нет
 
\bОписание функции:\p
          Функция возвращает указатель на таблицу
          параметров диска 1
 
\bВозвращаемое значение:\p
          Указатель на таблицу параметров диска 1 HDPT
 
 
 ─────────────────────────────────────────────────────────────────────────────────────
.context get_hdp2
.context @L801c
:l15
:nФункция get_hdp2
\a\u< Назад >\vsysp13\v \a< Оглавление >\vsysp\v \a< Пример >\vdiscshow.c\v\p
─────────────────────────────────────────────────────────────────────────────────────
 
\bПрототип функции:\p
          HDPT _far *get_hdp2(void);
 
\bПараметры функции:\p
          Нет
 
\bОписание функции:\p
          Функция возвращает указатель на таблицу
          параметров диска 2
 
\bВозвращаемое значение:\p
          Указатель на таблицу параметров диска 2 HDPT
 
 
 ─────────────────────────────────────────────────────────────────────────────────────
.context getbiosi
.context @L801d
:l15
:nФункция getbiosi
\a\u< Назад >\vsysp13\v \a< Оглавление >\vsysp\v \a< Пример >\vshowbios.c\v\p
─────────────────────────────────────────────────────────────────────────────────────
 
\bПрототип функции:\p
          BIOS_ID _far *getbiosi(void);
 
\bПараметры функции:\p
          Нет
 
\bОписание функции:\p
          Функция возвращает адрес идентификатора BIOS,
          имеющего следующую структуру:
 
                 typedef struct _BIOS_ID_ {
 
                    char date[8];
                    unsigned reserve;
                    char pc_type;
 
                 } BIOS_ID;
 
          В этой структуре:
 
             date    - дата изготовления BIOS;
             reserve - зарезервировано;
             pc_type - код типа компьютера.
 
\bВозвращаемое значение:\p
          Адрес идентификатора BIOS
 
 
 ─────────────────────────────────────────────────────────────────────────────────────
.context getboot
.context @L801e
:l15
:nФункция getboot
\a\u< Назад >\vsysp13\v \a< Оглавление >\vsysp\v \a< Пример >\vbootshow.c\v\p
─────────────────────────────────────────────────────────────────────────────────────
 
\bПрототип функции:\p
          int getboot(BOOT _far *boot, int drive);
 
\bПараметры функции:\p
          boot        - указатель на буфер, в который
                        будет считана загрузочная
                        запись
 
          drive       - номер физического НМД
                        (0 - первый НМД, 1 - второй,...)
 
\bОписание функции:\p
          Функция считывает загрузочную запись
          для указанного НМД.
 
\bВозвращаемое значение:\p
          0 - если загрузочная запись считана
              успешно;
          1 - произошла ошибка
 
 
 ─────────────────────────────────────────────────────────────────────────────────────
.context getmboot
.context @L801f
:l15
:nФункция getmboot
\a\u< Назад >\vsysp13\v \a< Оглавление >\vsysp\v \a< Пример >\vpartshow.c\v\p
─────────────────────────────────────────────────────────────────────────────────────
 
\bПрототип функции:\p
          int getmboot(MBOOT *master_boot, int drive);
 
\bПараметры функции:\p
          master_boot - указатель на буфер, в который
                        будет считана главная загрузочная
                        запись
 
          drive       - номер физического НМД
                        (0 - первый НМД, 1 - второй,...)
 
\bОписание функции:\p
          Функция считывает главную загрузочную запись
          для указанного НМД.
 
\bВозвращаемое значение:\p
          0 - если главная загрузочная запись считана
              успешно;
          Код ошибки, полученный от функции BIOS "Чтение
              сектора" - если чтение главной загрузочной
              записи выполнить невозможно.
 
 
 ─────────────────────────────────────────────────────────────────────────────────────
.context heof
.context @L8020
:l15
:nФункция heof
\a\u< Назад >\vsysp13\v \a< Оглавление >\vsysp\v \a< Пример >\vcopyf1.c\v\p
─────────────────────────────────────────────────────────────────────────────────────
 
\bПрототип функции:\p
          int heof(int handle);
 
\bПараметры функции:\p
          handle      - файловый номер (хендл) для
                        которого необходимо получить
                        информцию о состоянии
 
\bОписание функции:\p
          Функция позволяет проверить факт достижения
          конца файла или готовность устройства
 
\bВозвращаемое значение:\p
          0           - конец файла не достигнут (для файла),
                        устройство готово (для устройства);
 
          1           - достигнут конец файла (для файла),
                        устройство не готово (для устройства);
 
         -1           - произошла ошибка.
 
 
 ─────────────────────────────────────────────────────────────────────────────────────
.context pc_model
.context @L8021
:l15
:nФункция pc_model
\a\u< Назад >\vsysp13\v \a< Оглавление >\vsysp\v \a< Пример >\vdisk_ctl.c\v\p
─────────────────────────────────────────────────────────────────────────────────────
 
\bПрототип функции:\p
          char unsigned pc_model(void);
 
\bПараметры функции:\p
          Нет
 
\bОписание функции:\p
          Функция возвращает байт, идентифицирующий
          модель персонального компьютера
 
\bВозвращаемое значение:\p
          Код модели персонального компьютера:
 
             0xff - оригинальный PC;
             0xfe - XT, Portable PC;
             0xfd - PCjr;
             0xfc - AT;
             0xfb - XT с памятью 640К;
             0xf9 - Convertible PC.
 
 
 ─────────────────────────────────────────────────────────────────────────────────────
.context discshow.c
.context @L8022
\a\u< Назад >\vsysp13\v \a< Оглавление >\vsysp\v\p
───────────────────────────────────────────────────────────────────────────────────
#include <stdio.h>
#include <dos.h>
#include "sysp.h"
 
void main(void);
void main(void) {
 
  DISK_CONFIG cfg;
  DPT  _far *dpt_ptr;
  HDPT _far *hdpt1_ptr;
  HDPT _far *hdpt2_ptr;
 
  printf("\\n"
         "\\nКонфигурация дисковой подсистемы"
         "\\n  (C)Фролов А., 1991"
         "\\n");
 
// Определяем конфигурацию дисковой подсистемы
 
  disk_cfg(&cfg);
 
  printf("\\nУстановлено:"
         "\\n   Флоппи-дисков: %d"
         "\\n   Дисков:        %d",
         cfg.n_floppy,
         cfg.n_hard);
 
  printf("\\nТипы флоппи-дисков:  A: - %d, B: - %d"
         "\\nТипы дисков:         C: - %d, D: - %d",
         cfg.t_floppy1, cfg.t_floppy2,
         cfg.t_hard1,   cfg.t_hard2);
 
// Получаем адрес таблицы параметров дискеты
 
  dpt_ptr = get_dpt();
 
  printf("\\n"
         "\\nКод размера сектора дискеты:                   %d"
         "\\nЗаполняющий символ для форматирования дискеты: %2.2X",
         dpt_ptr->sec_size,
         dpt_ptr->fill_char);
 
// Получаем адреса первой и второй таблицы
// параметров жесткого диска
 
  hdpt1_ptr = get_hdp1();
  hdpt2_ptr = get_hdp2();
 
  printf("\\n"
         "\\nПараметры первого диска:"
         "\\n   Количество цилиндров:     %d"
         "\\n   Количество головок:       %d"
         "\\n"
         "\\nПараметры второго диска:"
         "\\n   Количество цилиндров:     %d"
         "\\n   Количество головок:       %d",
         hdpt1_ptr->max_cyl,
         hdpt1_ptr->max_head,
         hdpt2_ptr->max_cyl,
         hdpt2_ptr->max_head);
 
}
───────────────────────────────────────────────────────────────────────────────────
.context dirlist.c
.context @L8023
\a\u< Назад >\vsysp13\v \a< Оглавление >\vsysp\v\p
───────────────────────────────────────────────────────────────────────────────────
#include <stdio.h>
#include <malloc.h>
#include <dos.h>
#include "sysp.h"
 
void main(void);
void main(void) {
 
  BOOT _far *boot_rec;
  int i,j, k, status, fat_sectors;
  unsigned total_sectors;
  int ffat, root_begin, root_sectors;
  char drive;
  unsigned _far *fat_buffer;
  FITEM _far *root_buffer, _far *rptr;
  char cbuf[128];
  char _far *clust_buffer;
  int cur_clust;
 
  union REGS reg;
  struct SREGS segreg;
 
 
  printf("\\n"
         "\\nЧтение каталогов логического диска"
         "\\n  (C)Фролов А., 1991"
         "\\n");
 
 
// Заказываем буфер для чтения BOOT-записи.
// Адрес буфера присваиваем FAR-указателю.
 
  boot_rec = _fmalloc(sizeof(*boot_rec));
 
// Запрашиваем диск, для которого необходимо
// выполнить чтение загрузочной записи.
 
  printf("\\n"
         "\\nВведите обозначение диска (A, B, ...):");
 
  drive = getche();
 
// Вычисляем номер дисковода
 
  drive = toupper(drive) - 'A';
 
// Читаем загрузочную запись в буфер
 
  status = getboot((BOOT _far*)boot_rec, drive);
 
// Если произошла ошибка (например, неправильно указано
// обозначение диска), завершааем работу программы
 
  if(status) {
      printf("\\nОшибка при чтении BOOT-сектора");
      exit(-1);
  }
 
// Определяем формат таблицы FAT
 
  total_sectors = boot_rec->bpb.totsecs;
 
// Если мы работаем с расширенным разделом диска,
// общее количество секторов на диска берем из
// расширенного PBP
 
  if(total_sectors == 0) total_sectors = boot_rec->bpb.drvsecs;
 
// Формат FAT определяем исходя из общего
// количества секторов на логическом диске
 
  if(total_sectors > 20740) {
      printf("\\nFAT имеет 16-битовый формат");
      ffat=16;
  }
  else {
      printf("\\nFAT имеет 12-битовый формат");
      ffat=12;
  }
 
// Определяем количество секторов, занимаемых FAT
 
  fat_sectors = boot_rec->bpb.fatsize;
 
// Заказываем буфер для FAT
 
  fat_buffer = _fmalloc(fat_sectors * boot_rec->bpb.sectsize);
 
// Вычисляем номер первого сектора FAT
 
  j = boot_rec->bpb.ressecs;
 
// Читаем FAT в буфер fat_buffer
 
// Заполняем регистровые структуры для вызова
// прерывания DOS INT 25h
 
    reg.x.ax = drive;
    reg.x.bx = FP_OFF(fat_buffer);
    segreg.ds = FP_SEG(fat_buffer);
    reg.x.cx = fat_sectors;
    reg.x.dx = j;
    int86x(0x25, &reg, &reg, &segreg);
 
// Извлекаем из стека оставшееся там после
// вызова прерывания слово
 
    _asm pop ax
 
// Вычисляем номер первого сектора корневого каталога
 
   root_begin = j + fat_sectors * boot_rec->bpb.fatcnt;
 
// Вычисляем длину корневого каталога
 
   root_sectors = (boot_rec->bpb.rootsize * 32) /
                  boot_rec->bpb.sectsize;
 
// Заказываем буфер для корневого каталога
 
   root_buffer = _fmalloc(root_sectors * boot_rec->bpb.sectsize);
 
// Читаем корневой каталог в буфер root_buffer
 
    reg.x.ax = drive;
    reg.x.bx = FP_OFF(root_buffer);
    segreg.ds = FP_SEG(root_buffer);
    reg.x.cx = root_sectors;
    reg.x.dx = root_begin;
    int86x(0x25, &reg, &reg, &segreg);
    _asm pop ax
 
// Показываем содержимое корневого каталога
 
   printf("\\n"
          "\\nИмя файла    Аттр. Дата        Время     Кластер Размер"
          "\\n------------ ----- ----------  --------  ------- ------");
 
   for(rptr = root_buffer;;rptr++) {
      printf("\\n");
 
// Признак конца каталога - нулевой байт в начале
// имени файла
 
      if(rptr->name[0] == 0) break;
 
// Выводим содержимое дескриптора файла
 
      for(i=0; i<8; i++) printf("%c",rptr->name[i]);
      printf(".");
      for(i=0; i<3; i++) printf("%c",rptr->ext[i]);
      printf(" %02X    %02d-%02d-%02d  %02d:%02d:%02d ",
         rptr->attr,
         rptr->date.day,
         rptr->date.month,
         rptr->date.year + 1980,
         rptr->time.hour,
         rptr->time.min,
         rptr->time.sec * 2);
      printf(" %-5d   %lu",
         rptr->cluster_nu,
         rptr->size);
 
   }
 
// Получаем буфер для чтения кластеров каталога
 
   clust_buffer = _fmalloc(boot_rec->bpb.clustsize
                  * boot_rec->bpb.sectsize);
 
   printf("\\nНомер первого кластера каталога:");
   gets(cbuf);
   cur_clust = atoi(cbuf);
 
// Переменная k используется в качестве флага.
// При первом просмотре каталога ее значение равно 0,
// затем эта переменная устанавливается в 1.
 
   k=0;
 
   for(;;) {
 
// Сохраняем номер кластера каталога
 
      j=cur_clust;
 
// Вычисляем номер следующего кластера, распределенного
// каталогу
 
      cur_clust = fat(fat_buffer, ffat, cur_clust);
      printf("%d ",cur_clust);
 
// Читаем кластер в буфер clust_buffer
 
       reg.x.ax = drive;
       reg.x.bx = FP_OFF(clust_buffer);
       segreg.ds = FP_SEG(clust_buffer);
       reg.x.cx = boot_rec->bpb.clustsize;
       reg.x.dx = root_begin + root_sectors
                  + ((j-2)*boot_rec->bpb.clustsize);
       int86x(0x25, &reg, &reg, &segreg);
       _asm pop ax
 
// Показываем содержимое каталога
 
       rptr = (FITEM _far *)clust_buffer;
 
// Первый дескриптор в каталоге указывает на
// этот же каталог. В поле имени первого дескриптора
// находится строка ".       ". Этот факт можно использовать
// для проверки каталога. Если вы по ошибке указали
// номер кластера, не принадлежащего каталогу,
// программа завершит работу с сообщением об ошибке.
 
       if(k == 0) {
         k=1;
         if(strncmp(rptr->name,".       ",8) != 0) {
            printf("\\nЭто не каталог !");
            exit(-1);
         }
       }
 
       printf("\\n"
          "\\nИмя файла    Аттр. Дата        Время     Кластер Размер"
          "\\n------------ ----- ----------  --------  ------- ------");
 
       for(;;rptr++) {
         printf("\\n");
 
// Признак конца каталога - нулевой байт в начале
// имени файла
 
         if(rptr->name[0] == 0) break;
 
// Выводим содержимое дескриптора файла
 
         for(i=0; i<8; i++) printf("%c",rptr->name[i]);
         printf(".");
         for(i=0; i<3; i++) printf("%c",rptr->ext[i]);
         printf(" %02X    %02d-%02d-%02d  %02d:%02d:%02d ",
            rptr->attr,
            rptr->date.day,
            rptr->date.month,
            rptr->date.year + 1980,
            rptr->time.hour,
            rptr->time.min,
            rptr->time.sec * 2);
         printf(" %-5d   %lu",
            rptr->cluster_nu,
            rptr->size);
 
      }
 
// Если этот кластер - последний из распределенных каталогу,
// завершаем работу программы
 
      if((cur_clust == 0xfff) || (cur_clust == 0xffff)) break;
 
   }
 
// Освобождаем буфера
 
  _ffree(root_buffer);
  _ffree(boot_rec);
  _ffree(fat_buffer);
  _ffree(clust_buffer);
}
───────────────────────────────────────────────────────────────────────────────────
.context show_di.c
.context @L8024
\a\u< Назад >\vsysp13\v \a< Оглавление >\vsysp\v\p
───────────────────────────────────────────────────────────────────────────────────
#include <dos.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
 
void main(int argc, char *argv[]);
 
void main(int argc, char *argv[]) {
 
    int handle;
    int info;
    int rc;
 
// Открываем файл или устройство с заданным именем
 
    handle = open(argv[1], O_RDONLY);
 
// Если открыть невозможно, выводим сообщение
// и завершаем работу программы
 
    if(handle == -1) {
      printf("Не могу открыть файл!\\n");
      exit(-1);
    }
 
// Получаем информацию для хендла handle
 
    rc = get_devi(handle, &info);
 
    if(rc != 0) {
      printf("Ошибка с кодом %d\\n", rc);
      exit(-1);
    }
 
    printf("\\nСлово информации об устройстве: %04X",info);
 
}
 
───────────────────────────────────────────────────────────────────────────────────
.context showbios.c
.context @L8025
\a\u< Назад >\vsysp13\v \a< Оглавление >\vsysp\v\p
───────────────────────────────────────────────────────────────────────────────────
#include <stdio.h>
#include <stdlib.h>
#include "sysp.h"
 
void main(void);
 
void main(void) {
 
    BIOS_ID _far *id;
    int i;
 
    id = getbiosi();
 
    printf("\\nИдентификатор BIOS:"
           "\\n"
           "\\nДата изготовления: ");
 
    for(i=0; i<8; i++) {
      putch(id->date[i]);
    }
 
    printf("\\nРезервное поле:    %04.4X"
           "\\nТип компьютера:    %02.2X"
           "\\n",
           id->reserve,
           (unsigned char)id->pc_type);
 
    exit(0);
}
 
───────────────────────────────────────────────────────────────────────────────────
.context bootshow.c
.context @L8026
\a\u< Назад >\vsysp13\v \a< Оглавление >\vsysp\v\p
───────────────────────────────────────────────────────────────────────────────────
#include <stdio.h>
#include <malloc.h>
#include <dos.h>
#include "sysp.h"
 
void main(void);
void main(void) {
 
  BOOT _far *boot_rec;
  int i,j, k, status;
  char drive;
 
  printf("\\n"
         "\\nЧтение загрузочной записи логического диска"
         "\\n  (C)Фролов А., 1991"
         "\\n");
 
 
// Заказываем буфер для чтения BOOT-записи.
// Адрес буфера присваиваем FAR-указателю.
 
  boot_rec = _fmalloc(sizeof(*boot_rec));
 
// Запрашиваем диск, для которого необходимо
// выполнить чтение загрузочной записи.
 
  printf("\\n"
         "\\nВведите обозначение диска, для просмотра"
         "\\nзагрузочной записи (A, B, ...):");
 
  drive = getche();
 
// Вычисляем номер дисковода
 
  drive = toupper(drive) - 'A';
 
// Читаем загрузочную запись в буфер
 
  status = getboot((BOOT _far*)boot_rec, drive);
 
// Если произошла ошибка (например, неправильно указано
// обозначение диска), завершааем работу программы
 
  if(status) {
      printf("\\nОшибка при чтении BOOT-сектора");
      exit(-1);
  }
 
  printf("\\nСодержимое BOOT-сектора для диска %c",drive+'A');
  printf("\\n"
         "\\nOEM - название фирмы и версия DOS - ");
 
  for(i=0;i<8;i++) printf("%c",boot_rec->oem[i]);
 
  printf("\\nНомер диска                       - %x"
         "\\nПризнак расширенной BOOT-записи   - %c"
         "\\nСерийный номер диска              - %04X-%04X"
         "\\nМетка диска                       - ",
         (unsigned char)boot_rec->drive,
         boot_rec->signature,
         boot_rec->volser_hi,
         boot_rec->volser_lo);
 
  for(i=0;i<11;i++) printf("%c",boot_rec->label[i]);
 
  printf("\\nФормат FAT                        - ");
  for(i=0;i<8;i++) printf("%c",boot_rec->fat_format[i]);
 
  printf("\\n\\nИнформация из BPB:\\n");
 
  printf("\\nКоличество байтов в секторе       - %d"
         "\\nКоличество секторов в кластере    - %d"
         "\\nЗарезервировано секторов          - %d"
         "\\nКоличество копий FAT              - %d"
         "\\nМакс. количество файлов в корневом каталоге - %d"
         "\\nОбщее количество секторов на диске          - %d"
         "\\nБайт-описатель среды              - %x"
         "\\nКоличество секторов в FAT         - %d",
         boot_rec->bpb.sectsize,
         boot_rec->bpb.clustsize,
         boot_rec->bpb.ressecs,
         boot_rec->bpb.fatcnt,
         boot_rec->bpb.rootsize,
         boot_rec->bpb.totsecs,
         (unsigned char)boot_rec->bpb.media,
         boot_rec->bpb.fatsize);
 
  printf("\\n\\nИнформация из расширения BPB:\\n");
 
  printf("\\nСекторов на дорожке               - %d"
         "\\nКоличество головок                - %d"
         "\\nСкрытых секторов для диска < 32M  - %d"
         "\\nСкрытых секторов для диска >= 32M - %d"
         "\\nВсего секторов на диске           - %u",
         boot_rec->bpb.seccnt,
         boot_rec->bpb.headcnt,
         boot_rec->bpb.hiddensec_low,
         boot_rec->bpb.hiddensec_hi,
         boot_rec->bpb.totsecs);
 
// Освобождаем буфер
 
  _ffree(boot_rec);
}
───────────────────────────────────────────────────────────────────────────────────
.context partshow.c
.context @L8027
\a\u< Назад >\vsysp13\v \a< Оглавление >\vsysp\v\p
───────────────────────────────────────────────────────────────────────────────────
#include <stdio.h>
#include <dos.h>
#include "sysp.h"
 
void main(void);
void main(void) {
 
  DISK_CONFIG cfg;
  MBOOT mb;
  int i,j, k, status;
 
  printf("\\n"
         "\\nТаблицы разделов диска"
         "\\n  (C)Фролов А., 1991"
         "\\n");
 
// Определяем конфигурацию дисковой подсистемы
 
  disk_cfg(&cfg);
 
// Записываем в переменную i количество
// установленных в системе НМД
 
  j = cfg.n_hard;
  printf("\\nУстановлено дисков: %d", j);
 
// Для каждого НМД выводим содержимое
// таблицы разделов
 
  for(i=0;i<j;i++) {
 
// Читаем главную загрузочную запись
 
      status = getmboot(&mb,i);
      if(status != 0) {
         printf("\\nОшибка чтения диска %d, код ошибки: %d",
               i, status);
         exit(1);
      }
 
      printf("\\n\\nТаблица разделов диска %d",i);
      printf("\\n"
 
"\\n------------------------------------------------------------"
"\\n|Флаг|Начало раздела |Конец раздела  |Код  |Размер |Отн.   |"
"\\n|    |---------------|---------------|сист.|раздела|номер  |"
"\\n|    |Гол.|Сект.|Цил.|Гол.|Сект.|Цил.|     |       |сектора|"
"\\n|----|----|-----|----|----|-----|----|-----|-------|-------|"
"\\n");
 
      for(k=0; k<4; k++) {
         printf("|%3d |%4d|%4d |%4d|%4d|%4d |%4d|%5d|%7u|",
         mb.part_table[k].flag,
         mb.part_table[k].beg_head,
         mb.part_table[k].beg_sec_cyl & 0x3f,
         (mb.part_table[k].beg_sec_cyl >> 6) & 0x3ff,
         mb.part_table[k].end_head,
         mb.part_table[k].end_sec_cyl & 0x3f,
         (mb.part_table[k].end_sec_cyl >> 6) & 0x3ff,
         mb.part_table[k].sys,
         mb.part_table[k].size);
         printf("%7u|\\n",
            mb.part_table[k].rel_sec);
      }
      printf("------------------------------------------------------------");
  }
}
───────────────────────────────────────────────────────────────────────────────────
.context copyf1.c
.context @L8028
\a\u< Назад >\vsysp13\v \a< Оглавление >\vsysp\v\p
───────────────────────────────────────────────────────────────────────────────────
#include <io.h>
#include <conio.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys\\types.h>
#include <sys\\stat.h>
#include <malloc.h>
#include <errno.h>
 
void main(int, char *[]);
void main(int argc, char *argv[]) {
 
    int source, taget, i;
    char *buffer;
    unsigned count;
 
    if(argc == 3) {
 
// Открываем исходный копируемый файл
 
       if((source = open(argv[1], O_BINARY | O_RDONLY)) == - 1) {
 
           printf("\\nОшибка при открытии исходного файла: %d",
           errno);
           exit(-1);
 
       }
 
// Открываем выходной файл. При необходимости создаем
// новый. Если файл уже существует, выводим на экран
// запрос на перезапись содержимого существующего файла
 
      taget = open(argv[2], O_BINARY | O_WRONLY | O_CREAT | O_EXCL,
                            S_IREAD | S_IWRITE);
      if(errno == EEXIST) {
 
         printf("\\nФайл существует. Перезаписать? (Y,N)\\n");
 
// Ожидаем ответ оператора и анализируем его
 
         i = getch();
         if((i == 'y') || (i == 'Y'))
            taget = open(argv[2], O_BINARY | O_WRONLY | O_CREAT | O_TRUNC,
                                  S_IREAD | S_IWRITE);
 
      }
 
// Если выходной файл открыть невозможно, выводим
// сообщение об ошибке и завершаем работу программы
 
      if(taget == -1){
           printf("\\nОшибка при открытии выходного файла: %d",
           errno);
           exit(-1);
      }
 
// Будем читать и писать за один раз 10000 байтов
 
      count = 10000;
 
// Заказываем буфер для передачи данных
 
      if((buffer = (char *)malloc(count)) == NULL) {
           printf("\\nНедостаточно оперативной памяти");
           exit(-1);
      }
 
 
// Копируем исходный файл
 
      while(!heof(source)) {
 
// Читаем count байтов в буфер buffer
 
         if((count = read(source, buffer, count)) == -1) {
           printf("\\nОшибка при чтении: %d",
           errno);
           exit(-1);
         }
 
// Выполняем запись count байтов из буфера в выходной файл
 
         if((count = write(taget, buffer, count)) == - 1) {
           printf("\\nОшибка при записи: %d",
           errno);
           exit(-1);
         }
      }
 
// Закрываем входной и выходной файлы
 
      close(source);
      close(taget);
 
// Освобождаем память, заказанную под буфер
 
      free(buffer);
    }
 
// Если при запуске программы не были указаны
// пути для входного или выходного файла,
// выводим сообщение об ошибке
 
    else
        printf("\\n"
               "Задайте пути для исходного"
               " и результирующего файлов!\\n");
}
 
───────────────────────────────────────────────────────────────────────────────────
.context disk_ctl.c
.context @L8029
\a\u< Назад >\vsysp13\v \a< Оглавление >\vsysp\v\p
───────────────────────────────────────────────────────────────────────────────────
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <dos.h>
#include "sysp.h"
 
#define CYL 0
 
void main(void);
void fdc_out(unsigned char byte);
int  fdc_inp(void);
void int_wait(void);
void dma_init(char *);
 
void main(void) {
 
   unsigned i;
   long l;
   char buffer[512];
   char status[7], main_status;
   DPT _far *fdpt;
   FILE *sect;
 
   printf("\\n"
          "\\nРабота с контроллером НГМД"
          "\\n  (C)Фролов А., 1991"
          "\\n");
 
 
// Эта программа предназначена только для IBM AT
 
   if(pc_model() != 0xfc) {
      printf("Эта программа предназначена только для IBM AT\\n");
      exit(-1);
   }
 
// Открываем файл, в который будем записывать
// содержимое самого первого сктора на дискете
 
   sect = fopen("!sector.dat","wb+");
 
// Устанавливаем указатель на таблицу
// параметров дискеты
 
   fdpt = get_dpt();
 
// Включаем мотор дисковода А:
// Перед этим разрешаем прерывания
 
//   _enable();
   outp(0x3F2, 0x1C);
 
// Выполняем задержку для разгона двигателя
 
   for(l=0;l<200000;l++);
 
// Показываем содержимое регистра основного
// состояния контроллера
 
   printf("Мотор включен.\\t\\t");
   printf("Основное состояние: %02.2X\\n",inp(0x3F4));
 
// Перед чтением сектора необходимо установить
// головку на нужную дорожку, в нашем случае это
// дорожка с номером CYL.
 
// Выдаем контроллеру команду "Поиск"
 
   fdc_out(0xf);
 
// Для команды "Поиск" требуется два байта параметров:
// номер головки/номер накопителя и номер дорожки.
// Мы работаем с нулевой головкой накопителя А:,
// поэтому первый параметр равен 0, второй - CYL
 
   fdc_out(0);
   fdc_out(CYL);
 
// Показываем содержимое регистра основного
// состояния контроллера
 
   printf("\\n<<<Поиск>>> \\t\\t");
   printf("Основное состояние: %02.2X\\n",inp(0x3F4));
 
// Ожидаем прерывание по завершению операции
 
   int_wait();
 
// Задержка для позиционирования головки
 
   for(l=0;l<20000;l++);
 
// Для проверки результата выполнения команды
// "Поиск" выдаем контроллеру команду
// "Чтение состояния прерывания"
 
// Выводим содержимое регистра состояния
// ST0  и номер дорожки после выполнения команды
// "Поиск" PCN
 
   fdc_out(0x8);
   printf("Состояние прерывания:\\t");
   printf(" ST0: %02.2X, \\t", fdc_inp());
   printf("PCN: %02.2X\\n", fdc_inp());
 
// Для более глубокой диагностики состояния
// контроллера выдаем контроллеру команду
// "Чтение состояния накопителя", выводим
// содержимое регистра состояния ST3
 
   fdc_out(4);
   fdc_out(0);
   printf("Состояние накопителя:\\t ST3: %02.2X\\n",fdc_inp());
 
// Устанавливаем скорость передачи данных 500 Кбайтов/с,
// это значение может различаться для разных типов дискет
 
   outp(0x3F7, 0);
 
// Инициализация канала прямого
// доступа к памяти
 
   dma_init(buffer);
 
// Выдаем команду "Чтение данных"
 
   fdc_out(0x66);
   fdc_out(0x0);     // накопитель 0, головка 0
 
   fdc_out(CYL);     // цилиндр CYL
   fdc_out(0);       // головка 0
   fdc_out(1);       // номер сектора - 1
 
// Передаем контроллеру технические параметры
// дисковода, берем их из таблицы параметров дискеты.
// Это такие параметры:
//    - размер сектора;
//    - номер последнего сектора на дорожке;
//    - размер промежутка;
//    - число считываемых/записываемых байтов
 
   fdc_out(fdpt->sec_size);
   fdc_out(fdpt->eot);
   fdc_out(fdpt->gap_rw);
   fdc_out(fdpt->dtl);
 
// Ожидаем прерывание по завершению операции
 
   int_wait();
 
// Считываем и выводим на экран байты результата
// операции "Чтение данных"
 
   printf("\\n<<<Чтение сектора>>> \\n");
   printf("   Байты состояния (ST0,ST1,ST2,C,H,R,N):\\n");
 
   for(i=0; i<7; i++) printf("%02.2X\\t", (char) fdc_inp());
   printf("\\n");
 
// Выводим содержимое считанного сектора в файл
 
   for(i=0; i<512; i++) fputc(buffer[i],sect);
   fclose(sect);
 
// Выключаем мотор
 
   outp(0x3F2, 0xC);
}
 
 
// Вывод байта в контроллер дисковода
 
void fdc_out(unsigned char parm) {
 
   _asm {
      mov   dx,3F4h     // Порт основного состояния
loop_fdc_out:
 
      in    al,dx
      test  al,80h      // Проверяем готовность
      jz loop_fdc_out   //   контроллера
 
      inc   dx          // Выводим байт в порт данных
      mov   al, parm    //   контроллера
      out   dx, al
   }
}
 
// Ввод байта из порта данных контроллера дисковода
 
int fdc_inp(void) {
 
   _asm {
      mov   dx,3F4h     // Порт основного состояния
loop_fdc_inp:
      in    al,dx
      test  al,80h      // Проверяем готовность
      jz loop_fdc_inp   //   контроллера
 
      inc   dx          // Введенный байт записываем
      in    al, dx      // в регистр AX
   }
}
 
// Ожидание прерывания от контроллера
 
void int_wait(void) {
 
// Разрешаем прерывания
 
   _enable();
   _asm {
      mov   ax,40h         // После прихода прерывания
      mov   es,ax          // программа обработки прерывания
      mov   bx,3Eh         // устанавливает в 1 старший бит
wait_loop:                 // байта в области данных BIOS
      mov   dl,es:[bx]     // по адресу 0040:003E.
      test  dl,80h         // Мы ждем, когда этот бит будет
      jz    wait_loop      // установлен в 1, а затем
                           // сбрасываем его.
      and   dl,01111111b
      mov   es:[bx],dl
   }
}
 
// Инициализация канала прямого доступа к памяти
 
void dma_init(char *buf) {
 
   unsigned long f_adr;
   unsigned sg, of;
 
// Вычисляем 24-разрядный адрес буфера для данных
 
   f_adr = ((unsigned long)_psp << 4)
            + (((unsigned long)buf) & 0xffff);
 
// Расщепляем адрес на номер страницы
// и смещение
 
   sg = (f_adr >> 16) & 0xff;
   of = f_adr & 0xffff;
 
// На время программирования контроллера прямого
// доступа запрещаем прерывания
 
   _disable();
 
   _asm {
      mov   al,46h   // Команда чтения данных от
                     // контроллера НГМД.
 
      out   12,al    // Сброс триггера-указателя байта
                     // для работы с 16-разрядными портами.
                     // Следующий байт, выводимый в 16-разрядный
                     // порт будет интерпретироваться
                     // как младший.
 
      out   11,al    // Установка режима контроллера ПДП
 
      mov   ax,of    // Смещение буфера, младший байт
      out   4,al
      mov   al,ah    // Смещение буфера, старший байт
      out   4,al
 
      mov   ax,sg    // Номер страницы
      out   81h,al
 
      mov   ax,511   // Длина передаваемых данных
      out   5,al
      mov   al,ah
      out   5,al
 
      mov   al,2     // Разблокировка канала 2 контроллера ПДП
      out   10,al
   }
 
// Инициализация контроллера закончена,
// разрешаем прерывания.
 
   _enable();
}
───────────────────────────────────────────────────────────────────────────────────
 

 
