我们在应用程序中常见到用软件控制 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
; 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