#include <dos.h>
#include <stdio.h>
#include <conio.h>

typedef struct
{
  unsigned char type;
  unsigned owner;
  unsigned size;
  char reserve[11];
} MCB;
typedef MCB far* LPMCB;

typedef struct
{
  unsigned mcb_seg;
  void far *dev_cb;
  void far *file_tab;
  void far *clock_dr;
  void far *con_dr;
  unsigned max_btbl;
  void far *disk_buf;
  void far *drv_info;
  void far *fcb_tabl;
  unsigned fcb_size;
  unsigned char num_bdev;
  unsigned char lastdriv;
} CVT;
typedef CVT far* LPCVT;

LPMCB get_nmcb(LPMCB);

void main(void)
{
  union REGS regs;
  struct SREGS sregs;
  LPCVT lpCVT;
  LPMCB lpMCB;

  // Получаем адрес векторной таблицы связи
  regs.h.ah = 0x52;
  intdosx(&regs, &regs, &sregs);

  // Передвигаем указатель на поле msb_seg
  lpCVT = (LPCVT)MK_FP(sregs.es, regs.x.bx - 2);

  // Получаем указатель на первый блок MCB
  lpMCB = (LPMCB)MK_FP(lpCVT->mcb_seg, 0);

  printf("\nБлоки управления памятью MCB"
    "\n(C) Фролов А.В., 1995\n"
    "\nАдрес MCB Тип Владелец Размер"
    "\n--------- --- -------- ------"
    "\n");

  for(;;)
  {
    // Если последний блок MCB, выходим
    // из цикла
    if(lpMCB == NULL) break;

    // Выводим информацию о блоке MCB
    printf("%Fp %c   %04X     %04X\n",
      lpMCB, lpMCB->type,
      lpMCB->owner, lpMCB->size);

    // Получаем адрес следующего блока MCB
    lpMCB=get_nmcb(lpMCB);
  }

  printf("\nНажмите любую клавишу...");
  getch();
}

// ------------------------------------------
// get_nmcb
// Функция возвращает адрес следующего блока
// MCB или NULL, если это последний блок
// ------------------------------------------
LPMCB get_nmcb(LPMCB mcb)
{
  unsigned seg, off;

  // Проверяем тип блока
  if(mcb->type == 'M')
  {
    // Вычисляем адрес следующего MCB
    seg = FP_SEG(mcb) + mcb->size + 1;
    off = FP_OFF(mcb);
    return((MCB far *) MK_FP(seg,off));
  }
  else return((LPMCB)NULL);
}


