我们在应用程序中常见到用软件控制 CD-ROM 的出、入盒,本文就是实现这种功能的一个例子。主要用到 INT 2FH 的 1510H(Send device driver request) 功能。具体参数详见程序注释。
要用到的几个中断说明如下:
1. IOCTL input 的格式:
偏移量  | 类型  | 内容  | 
00H  | 字节  | 1AH  | 
01H  | 字节  | 00H  | 
02H  | 字节  | 03H  | 
03H  | 字节  | 11 DUP(?)  | 
0EH  | 双字  | 缓冲区地址  | 
12H  | 字  | 缓冲区长度  | 
14H  | 字节  | 6 DUP(?)  | 
2. IOCTL output 的格式:
偏移量  | 类型  | 内容  | 
00H  | 字节  | 1AH  | 
01H  | 字节  | 00H  | 
02H  | 字节  | 0CH  | 
03H  | 字节  | 11 DUP(?)  | 
0EH  | 双字  | 缓冲区地址  | 
12H  | 字  | 缓冲区长度  | 
14H  | 字节  | 6 DUP(?)  | 
3. 在缓冲区中填入命令再用 INT 2fH 的 1510H 便可以实现 CD-ROM 的各种功能,缓冲的一些命令格式如下:
作用  | 长度  | 格式  | 
出盒  | 1  | 00  | 
解锁  | 2  | 01,00  | 
加锁  | 2  | 01,01  | 
入盒  | 1  | 05  | 
取CD-ROM 状态  | 5  | 06,0,0,0,0 返回:06,xx,xx,0,0 xx,xx为状态字 位0:1 门开,0门关 位1:1未锁,0门锁 位B:1无盘,0有盘  | 
4. 检测 CD-ROM 驱动程序的存在:
AX = 1500H
BX = 0
INT 2fH
返回:BX = CD-ROM 个数
CX = 起始CD-ROM 盘符,0=A:,1=B:等等
5. 发送 Device Driver Request:
AX = 1510H
ES:BX=请求头地址
CX = CD-ROM 的盘号
源程序如下:
;       CD-ROM eject/load progrm by LuoYunBin
;       Ver 1.20 ------ Jan 6,1996
CODE    SEGMENT
ASSUME  CS:CODE,DS:CODE
ORG 100H
START:
jmp install
COPYRIGHT DB  'CD-ROM drive eject/close prg. V1.20',0dh,0ah
DB  'Copyright (c) by Luo Yun Bin, Jan 6,1996',0dh,0ah
DB  'http://asm.yeah.net,Email: luoyunbin@telekbird.com.cn'
DB  0dh,0ah,0ah,24h
D_HELP    DB  'Usage: EJ [drive:] [/?|/L|/U]',0dh,0ah
DB  '       /?  -------- Display this help',0dh,0ah
DB  '       /L  -------- Lock door',0dh,0ah
DB  '       /U  -------- Unlock door',0dh,0ah,24h
MESS_WAIT DB  '[ENTER] to close, [Esc] to quit.',24h
MESS_ESC  DB  'tray keep open...',0dh,0ah,24h
MESS_NO_CD  DB  'MSCDEX not installed!',0dh,0ah,24h
MESS_STATUS DB  'There are '
DRV_NUMBER  DB  '0 CD-ROM drive(s) starting at '
DRV   DB  'A:',0dh,0ah,24h
MESS_DRV  DB  0dh,'                                  ',0dh
DB  'drive '
DRV1    DB  'A: ',24h
MESS_EJECT  DB  'ejecting....',24h
MESS_CLOSE  DB  'closing ....',24h
MESS_LOCK DB  'locking ....',24h
MESS_UNLOCK DB  'unlocking...',24h
MESS_DONE DB  ' Done!',0dh,0ah,24h
CD_DRV    DW  ?
FLAG    DB  ?
;======================================================
REQ_HEAD  DB  1ah,0   ;IOCTL input
REQ_CMD   DB  3
REQ_ERR   DW  ?
DB  9 dup (0)
BUF_OFF   DW  buffer
BUF_SEG   DW  ?
BUF_LEN   DW  ?
DB  6 dup (0)
;======================================================
BUFFER    DB  5 dup (0) ;Max used 5 bytes
CMD_LINE  PROC
mov si,81h    ;处理命令行参数
mov di,80h
cld
cmd_reload:
lodsb
cmp al,0dh
jz  conv_end  ;将命令行小写字母换成大写
cmp al,'a'
jb  conv_ok
cmp al,'z'
ja  conv_ok
sub al,20h
conv_ok:
stosb
jmp short cmd_reload
conv_end:
xor al,al
stosb
mov si,80h
cmd_reload1:
lodsb
or  al,al
jz  cmd_end
cmp al,'/'
jz  cmd_switch
cmp al,':'
jnz cmd_reload1
mov al,[si-2]
cmp al,'A'
jb  cmd_end
cmp al,'Z'
ja  cmd_end
sub al,'A'
xor ah,ah
mov cd_drv,ax
jmp short cmd_reload1
cmd_switch:
lodsb
cmp al,'?'
jz  cmd_help
cmp al,'L'
jz  cmd_lock
cmp al,'U'
jz  cmd_unlock
jmp short cmd_reload1
cmd_end:
ret
cmd_help:
mov dx,offset d_help
call  print
int 20h
cmd_lock:
or  flag,1
jmp short cmd_reload1
cmd_unlock:
or  flag,2
jmp short cmd_reload1
CMD_LINE  ENDP
CD_INT    PROC
mov ax,1510h
mov buf_seg,cs
mov bx,offset req_head
mov     cx,cd_drv
int     2fh
ret
CD_INT    ENDP
GET_STATUS  PROC
mov     buffer,6
mov buf_len,5
mov req_cmd,3
call    cd_int
ret
GET_STATUS  ENDP
EJECT_DISK  PROC
mov dx,offset mess_drv
call  print
mov dx,offset mess_eject
call  print
mov buffer,0
mov buf_len,1
mov req_cmd,0ch
call    cd_int
mov     dx,offset mess_done
call    print
ret
EJECT_DISK      ENDP
CLOSE_TRAY      PROC
mov     dx,offset mess_drv
call    print
mov     dx,offset mess_close
call    print
mov buffer,5
mov buf_len,1
mov req_cmd,0ch
call  cd_int
mov     dx,offset mess_done
call    print
ret
CLOSE_TRAY      ENDP
LOCK_DOOR PROC
mov dx,offset mess_drv
call  print
mov dx,offset mess_lock
call  print
mov word ptr buffer,0101h
mov buf_len,2
mov req_cmd,0ch
call  cd_int
mov dx,offset mess_done
call  print
ret
LOCK_DOOR ENDP
UNLOCK_DOOR PROC
mov dx,offset mess_drv
call  print
mov dx,offset mess_unlock
call  print
mov word ptr buffer,0001h
mov buf_len,2
mov req_cmd,0ch
call  cd_int
mov dx,offset mess_done
call  print
ret
UNLOCK_DOOR ENDP
CHECK_CDROM     PROC
mov     ax,1500h
xor     bx,bx
int     2fh
or      bx,bx   ;BX = CD-ROM numbers
jnz     mscdex_installed
mov     dx,offset mess_no_cd
call    print
int     20h
mscdex_installed:
mov     bp,cx
xor     bh,bh
add     bp,bx
dec     bp
cmp     cd_drv,cx
jb      re_set
cmp     cd_drv,bp
jbe     par_ok
re_set:
mov     cd_drv,cx
par_ok:
add     drv_number,bl
add     drv,cl
mov     cx,cd_drv
add     drv1,cl
mov     dx,offset mess_status
call    print
ret
CHECK_CDROM     ENDP
PRINT   PROC
mov     ah,9
int     21h
ret
PRINT   ENDP
install:
mov     dx,offset copyright
call    print
call  cmd_line
call    check_cdrom   ;检测 CD-ROM 状态
test  flag,1      ;如果 /L 参数则 Lock_door
jz  ins1
call  lock_door
int 20h
ins1:
test  flag,2      ;如果 /U 参数则 unlock_door
jz  ins2
call  unlock_door
int 20h
ins2:
call    get_status
test  word ptr buffer+1,1 ;如果现在在出盒状态则转入盒
jnz close_it
call    eject_disk    ;打开 CD-ROM
mov     dx,offset mess_wait ;等待
call    print
xor     ax,ax
int     16h
cmp     al,1bh
jz      _esc_quit
close_it:
call    close_tray    ;关闭 CD-ROM
int     20h
_esc_quit:
mov     dx,offset mess_drv
call    print
mov     dx,offset mess_esc
call    print
int     20h
CODE    ENDS
END START









