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