  .MODEL tiny                                                                  
  .CODE
  ORG 0

drvioctl proc far

;===================================================
; Заголовок драйвера
;===================================================
  dd   0ffffffffh      ; адрес следующего драйвера
  dw   8000h           ; байт атрибутов
  dw   dev_strategy    ; адрес процедуры стратегии
  dw   dev_interrupt   ; адрес процедуры прерывания
  db   'IODRIVER'      ; имя устройства

;===================================================
; Программа стратегии
;===================================================
dev_strategy:
  mov  cs:req_seg, es
  mov  cs:req_off, bx
  ret

; Здесь запоминается адрес заголовка запроса
req_seg         dw ?
req_off         dw ?

;===================================================
; Обработчик прерывания
;===================================================

dev_interrupt:
  push es
  push ds
  push ax
  push bx
  push cx
  push dx
  push si
  push di
  push bp

  mov  ax, cs:req_seg
  mov  es, ax
  mov  bx, cs:req_off

  mov  al,es:[bx]+2
  shl  al,1
  sub  ah,ah         
  lea  di,functions 
  add  di,ax 
  jmp  word ptr [di] 

functions   LABEL  WORD

   dw   initialize
   dw   check_media
   dw   make_bpb
   dw   ioctl_in
   dw   input_data
   dw   nondestruct_in
   dw   input_status
   dw   clear_input
   dw   output_data
   dw   output_verify
   dw   output_status
   dw   clear_output
   dw   ioctl_out
   dw   Device_open
   dw   Device_close
   dw   Removable_media

check_media:
make_bpb:
ioctl_in:
nondestruct_in:
input_status:
clear_input:
output_verify:
output_status:
clear_output:
ioctl_out:
Removable_media:
Device_open:
Device_close:

  or   es:word ptr [bx]+3, 8103h
  jmp  quit

;===================================================
; Обработчик команды вывода данных
;===================================================

output_data:

; Записываем в регистр CL количество
; выводимых символов

  mov  cl, es:[bx]+18
  push cx

; Выводим сообщение о начале вывода

  mov ax, cs
  mov ds, ax
  mov si, offset outmsg
  call Puts

  pop cx

; Загружаем в DS:SI адрес буфера данных

  mov  ax, es:[bx]+16
  mov  ds, ax
  mov  si, es:[bx]+14

; Выводим на экран символы из буфера

out_loop:
  mov   ah, 02h
  mov   dl, ds:byte ptr [si]
  int   21h
  inc si
  loop out_loop
  jmp  quit

;===================================================
; Обработчик команды ввода данных
;===================================================

input_data:

; Записываем в регистр CL количество
; вводимых символов

  mov  cl, es:[bx]+18
  push cx

; Выводим сообщение о начале ввода

  mov ax, cs
  mov ds, ax
  mov si, offset inpmsg
  call Puts

; Загружаем в DS:SI адрес буфера данных

  pop  cx
  mov  ax, es:[bx]+16
  mov  ds, ax
  mov  di, es:[bx]+14

; Вводим символы с клавиатуры и записываем в буфер

inp_loop:
  mov  ax,0
  int  16h
  mov  ds:byte ptr [di], al
  mov   ah, 02h
  mov   dl, al
  int   21h
  inc di
  loop inp_loop
  jmp  quit

quit:
  or   es:word ptr [bx]+3, 100h
  pop bp
  pop di
  pop si
  pop dx
  pop cx
  pop bx
  pop ax
  pop ds
  pop es
  ret

;===================================================
; Процедура выводит на экран строку
; символов в формате ASCIIZ
;===================================================

Puts proc near
  push si
Puts_loop:
  cmp  ds:byte ptr [si], 0
  jz   end_Puts
  mov   ah, 02h
  mov   dl, ds:byte ptr [si]
  int   21h
  inc si
  jmp Puts_loop

end_Puts:
  pop si
  ret
Puts endp

hello db 13,10,'+--------------------------------+'
      db 13,10,'| *DRVIOCTL* (C)Frolov A., 1995  |'
      db 13,10,'+--------------------------------+'
      db 13,10,0

outmsg   DB 13,10,'Выведено: ',0
inpmsg   DB 13,10,'Введите символ: ',0

E_O_P:
initialize:

  lea  ax, E_O_P 
  mov  es:word ptr [bx]+14, ax
  mov  es:word ptr [bx]+16, cs

; Стираем экран

  mov   dh, 18h
  mov   dl, 80h

  xor   cx, cx
  mov   bh, 7
  xor   al, al
  mov   ah, 6
  int   10h

; Устанавливаем курсор в левый верхний угол экрана

  mov   bh, 0
  xor   dx, dx
  mov   ah, 2
  int   10h

; Выводим сообщение

  mov ax, cs
  mov ds, ax
  mov si, offset hello
  call Puts
  jmp  quit

drvioctl endp

  END drvioctl

