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