  .MODEL tiny
  .CODE

drvsimp proc far

; Отмечаем конец области памяти, которая
; будет резидентной в памяти. Так как наш
; драйвер не устанавливается резидентно,
; располагаем эту метку в начале драйвера

DriverEnd:

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

; ------------------------------------------------
; Программа стратегии
; ------------------------------------------------
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

; Устанавливаем ES:BX на заголовок запроса
  mov  ax, cs:req_seg
  mov  es, ax
  mov  bx, cs:req_off

; Получаем код команды из заголовка запроса и умножаем
; его на два, чтобы использовать в качестве индекса
; в таблице адресов обработчиков команд
  mov  al, es:[bx]+2
  shl  al, 1

  sub  ah, ah        ; записывем 0 в регистр 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:
output_data:
input_data:

  or   es:word ptr [bx]+3, 8103h
  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,'|  *DRVSIMP* (C)Frolov A., 1995  |'
	db 13,10,'+--------------------------------+'
	db 13,10
	db 13,10,'Press any key...'
	db 13,10,0

; ------------------------------------------------
; Выполнение инициализации драйвера
; ------------------------------------------------
initialize:

; Записываем адрес конца драйвера в заголовок
  lea  ax, DriverEnd
  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

; Ждем, когда пользователь нажмет любую клавишу
  mov   ax, 0
  int   16h

  jmp  quit
drvsimp   ENDP

  END drvsimp

