Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly MOV CX、(DEVRD SHL 8)或DRDWRHL在这个设备驱动程序中做什么?为什么将两种中断类型放入计数寄存器?_Assembly_X86 16_Device Driver - Fatal编程技术网

Assembly MOV CX、(DEVRD SHL 8)或DRDWRHL在这个设备驱动程序中做什么?为什么将两种中断类型放入计数寄存器?

Assembly MOV CX、(DEVRD SHL 8)或DRDWRHL在这个设备驱动程序中做什么?为什么将两种中断类型放入计数寄存器?,assembly,x86-16,device-driver,Assembly,X86 16,Device Driver,我想在我的代码中提到DEVRD=0000 0100(即十进制4或中断04h,用于溢出)和DRDWRHL=0001 0110(即十进制22或中断16h,用于键盘输入)。在这里,我感到困惑的是,为什么我们要将(0000 0100 SHL 8)放在CH中,将(0001 0110)放在CL中。这意味着我们要将两种中断类型(04h用于溢出,16h用于键盘输入)放在计数器寄存器CX中。计数器寄存器CX在这里做什么 更具体地说,这里DEVRD代表设备读,DRDWTHL代表设备读写头大小。提前谢谢 ; ; De

我想在我的代码中提到DEVRD=0000 0100(即十进制4或中断04h,用于溢出)和DRDWRHL=0001 0110(即十进制22或中断16h,用于键盘输入)。在这里,我感到困惑的是,为什么我们要将(0000 0100 SHL 8)放在CH中,将(0001 0110)放在CL中。这意味着我们要将两种中断类型(04h用于溢出,16h用于键盘输入)放在计数器寄存器CX中。计数器寄存器CX在这里做什么


更具体地说,这里DEVRD代表设备读,DRDWTHL代表设备读写头大小。提前谢谢

;
; Device call routines for MSDOS
;

INCLUDE DOSSEG.ASM

IFNDEF  KANJI
KANJI   EQU     0       ;FALSE
ENDIF

CODE    SEGMENT BYTE PUBLIC  'CODE'
    ASSUME  SS:DOSGROUP,CS:DOSGROUP

.xlist
.xcref
INCLUDE DOSSYM.ASM
INCLUDE DEVSYM.ASM
.cref
.list

TITLE   DEV - Device call routines
NAME    Dev

    i_need  IOXAD,DWORD
    i_need  IOSCNT,WORD
    i_need  DEVIOBUF,4
    i_need  IOCALL,BYTE
    i_need  IOMED,BYTE
    i_need  IORCHR,BYTE
    i_need  CALLSCNT,WORD
    i_need  DMAAdd,DWORD
    i_need  NullDevPt,DWORD
    i_need  CallDevAd,DWORD
    i_need  Attrib,BYTE
    i_need  NULDEV,DWORD
    i_need  Name1,BYTE
    i_need  DevPt,DWORD
    i_need  DPBHead,DWORD
    i_need  NumIO,BYTE
    i_need  ThisDPB,DWORD
    i_need  DevCall,DWORD
    i_need  VerFlg,BYTE

SUBTTL IOFUNC -- DO FUNCTION 1-12 I/O
PAGE
IOFUNC_RETRY:
ASSUME  DS:NOTHING,ES:NOTHING
    invoke  restore_world

    procedure   IOFUNC,NEAR
ASSUME  DS:NOTHING,ES:NOTHING

; Inputs:
;       DS:SI Points to FCB
;       AH is function code
;               = 0 Input
;               = 1 Input Status
;               = 2 Output
;               = 3 Output Status
;               = 4 Flush
;       AL = character if output
; Function:
;       Perform indicated I/O to device or file
; Outputs:
;       AL is character if input
;       If a status call
;               zero set if not ready
;               zero reset if ready (character in AL for input. 
status)
; For regular files:
;       Input Status
;               Gets character but restores fcb_RR field
;               Zero set on EOF
;       Input
;               Gets character advances fcb_RR field
;               Returns ^Z on EOF
;       Output Status
;               Always ready
; AX altered, all other registers preserved

    MOV     WORD PTR [IOXAD+2],SS
    MOV     WORD PTR [IOXAD],OFFSET. 
DOSGROUP:DEVIOBUF
    MOV     WORD PTR [IOSCNT],1
    MOV     WORD PTR [DEVIOBUF],AX

IOFUNC2:
    TEST    [SI.fcb_DEVID],080H
    JNZ     IOTODEV
    JMP     IOTOFILE

IOTODEV:
    invoke  save_world
    PUSH    DS
    PUSH    SS
    POP     ES
    PUSH    SS
    POP     DS
ASSUME  DS:DOSGROUP
    XOR     BX,BX
    MOV     [IOCALL.REQSTAT],BX
    MOV     BYTE PTR [IOMED],BL

    MOV     BX,OFFSET DOSGROUP:IOCALL

    MOV     CX,(DEVRD SHL 8) OR DRDWRHL   // I am in trouble here.
    OR      AH,AH
    JZ      DCALLR
    MOV     CX,(DEVRDND SHL 8) OR DRDNDHL
    DEC     AH
    JZ      DCALLR
    MOV     CX,(DEVWRT SHL 8) OR DRDWRHL
    DEC     AH
    JZ      DCALLO
    MOV     CX,(DEVOST SHL 8) OR DSTATHL
    DEC     AH
    JZ      DCALLO
DFLUSH:
    MOV     CX,(DEVIFL SHL 8) OR DFLSHL
DCALLR:
    MOV     AH,86H
DCALL:
    MOV     [IOCALL.REQLEN],CL
    MOV     [IOCALL.REQFUNC],CH
    MOV     CL,AH
    POP     DS
ASSUME  DS:NOTHING
    CALL    DEVIOCALL
    MOV     DI,[IOCALL.REQSTAT]
    TEST    DI,STERR
    JZ      OKDEVIO
    MOV     AH,CL
    invoke  CHARHARD
    CMP     AL,1
    JZ      IOFUNC_RETRY
;Know user must have wanted ignore. Make sure device. 
shows ready so
;that DOS doesn't get caught in a status loop when user. 
simply wants
;to ignore the error.
    AND     BYTE PTR [IOCALL.REQSTAT+1], NOT (STBUI. 
SHR 8)
OKDEVIO:
    PUSH    SS
    POP     DS
ASSUME  DS:DOSGROUP
    CMP     CH,DEVRDND
    JNZ     DNODRD
    MOV     AL,BYTE PTR [IORCHR]
    MOV     [DEVIOBUF],AL

DNODRD: MOV     AH,BYTE PTR [IOCALL.REQSTAT+1]
    NOT     AH                      ; Zero = busy, not zero = ready
    AND     AH,STBUI SHR 8

    invoke  restore_world
ASSUME  DS:NOTHING
    MOV     AX,WORD PTR [DEVIOBUF]
    return

DCALLO:
    MOV     AH,87H
    JMP     SHORT DCALL

IOTOFILE:
ASSUME  DS:NOTHING
    OR      AH,AH
    JZ      IOIN
    DEC     AH
    JZ      IOIST
    DEC     AH
    JZ      IOUT
    return                  ; NON ZERO FLAG FOR OUTPUT. 
STATUS

IOIST:
    PUSH    WORD PTR [SI.fcb_RR]        ; Save position
    PUSH    WORD PTR [SI.fcb_RR+2]
    CALL    IOIN
    POP     WORD PTR [SI.fcb_RR+2]      ; Restore position
    POP     WORD PTR [SI.fcb_RR]
    return

IOUT:
    CALL    SETXADDR
    invoke  STORE
    invoke  FINNOSAV
    CALL    RESTXADDR       ; If you change this into a jmp. 
don't come
    return                  ; crying to me when things don't work 
ARR

IOIN:
    CALL    SETXADDR
    invoke  LOAD
    PUSH    CX
    invoke  FINNOSAV
    POP     CX
    OR      CX,CX           ; Check EOF
    CALL    RESTXADDR
    MOV     AL,[DEVIOBUF]   ; Get byte from trans addr
    retnz
    MOV     AL,1AH          ; ^Z if EOF
    return

SETXADDR:
    POP     WORD PTR [CALLSCNT]     ; Return address
    invoke  save_world
    PUSH    WORD PTR [DMAADD]       ; Save Disk trans.   
addr
    PUSH    WORD PTR [DMAADD+2]
    PUSH    DS
    PUSH    SS
    POP     DS
ASSUME  DS:DOSGROUP
    MOV     CX,WORD PTR [IOXAD+2]
    MOV     WORD PTR [DMAADD+2],CX
    MOV     CX,WORD PTR [IOXAD]
    MOV     WORD PTR [DMAADD],CX    ; Set byte trans. 
addr
    MOV     CX,[IOSCNT]             ; ioscnt specifies length of 
buffer
    POP     DS
ASSUME  DS:NOTHING
    MOV     [SI.fcb_RECSIZ],1           ; One byte per record
    MOV     DX,SI                   ; FCB to DS:DX
    invoke  GETRRPOS
    JMP     SHORT RESTRET           ; RETURN ADDRESS

RESTXADDR:
    POP     WORD PTR [CALLSCNT]     ; Return address
    POP     WORD PTR [DMAADD+2]     ; Restore Disk trans 
addr
    POP     WORD PTR [DMAADD]
    invoke  restore_world
RESTRET:JMP     WORD PTR [CALLSCNT]      ; Return 
address
IOFUNC  ENDP

SUBTTL DEVIOCALL, DEVIOCALL2 - CALL A DEVICE
PAGE
    procedure   DEVIOCALL,NEAR
ASSUME  DS:NOTHING,ES:NOTHING

; Inputs:
;       DS:SI Points to device FCB
;       ES:BX Points to request data
; Function:
;       Call the device
; Outputs:
;       None
; DS:SI,AX destroyed, others preserved

    LDS     SI,DWORD PTR [SI.fcb_FIRCLUS]

   entry   DEVIOCALL2
; As above only DS:SI points to device header on entry, 
and DS:SI is preserved
    MOV     AX,[SI.SDEVSTRAT]
    MOV     WORD PTR [CALLDEVAD],AX
    MOV     WORD PTR [CALLDEVAD+2],DS
    CALL    DWORD PTR [CALLDEVAD]
    MOV     AX,[SI.SDEVINT]
    MOV     WORD PTR [CALLDEVAD],AX
    CALL    DWORD PTR [CALLDEVAD]
    return
DEVIOCALL   ENDP

SUBTTL DEVNAME - LOOK FOR NAME OF DEVICE
PAGE
    procedure   DEVNAME,NEAR
ASSUME  DS:DOSGROUP,ES:DOSGROUP

; Inputs:
;       DS,ES:DOSGROUP
;       Filename in NAME1
; Function:
;       Determine if file is in list of I/O drivers
; Outputs:
;       Carry set if name not found
;       ELSE
;       Zero flag set
;       BH = Bit 7,6 = 1, bit 5 = 0 (cooked mode)
;            bits 0-4 set from low byte of attribute word
;       DEVPT = DWORD pointer to Device header of device
; Registers BX destroyed

    PUSH    SI
    PUSH    DI
    PUSH    CX

    IF      KANJI
    PUSH    WORD PTR [NAME1]
    CMP     [NAME1],5
    JNZ     NOKTR
    MOV     [NAME1],0E5H
NOKTR:
    ENDIF

    TEST    BYTE PTR [ATTRIB],attr_volume_id ; If looking 
for VOL id don't find devs
    JNZ     RET31
    MOV     SI,OFFSET DOSGROUP:NULDEV
LOOKIO:
ASSUME  DS:NOTHING
    TEST    [SI.SDEVATT],DEVTYP
    JZ      SKIPDEV                 ; Skip block devices
    PUSH    SI
    ADD     SI,SDEVNAME
    MOV     DI,OFFSET DOSGROUP:NAME1
    MOV     CX,4                    ; All devices are 8 letters
    REPE    CMPSW                   ; Check for name in list
    POP     SI
    JZ      IOCHK                   ; Found it?
SKIPDEV:
    LDS     SI,DWORD PTR [SI]       ; Get address of next 
device
    CMP     SI,-1                   ; At end of list?
    JNZ     LOOKIO
RET31:  STC                             ; Not found
RETNV:  PUSH    SS
    POP     DS
ASSUME  DS:DOSGROUP

    IF      KANJI
    POP     WORD PTR [NAME1]
    ENDIF

    POP     CX
    POP     DI
    POP     SI
    RET

IOCHK:
ASSUME  DS:NOTHING
    MOV     WORD PTR [DEVPT+2],DS         ; Save pointer to 
device
    MOV     BH,BYTE PTR [SI.SDEVATT]
    OR      BH,0C0H
    AND     BH,NOT 020H             ;Clears Carry
    MOV     WORD PTR [DEVPT],SI
    JMP     RETNV
DevName ENDP

    procedure   GetBP,NEAR
ASSUME  DS:DOSGROUP,ES:NOTHING

; Inputs:
;       AL = Logical unit number (A = 0)
; Function:
;       Find Drive Parameter Block
; Outputs:
;       ES:BP points to DPB
;       [THISDPB] = ES:BP
;       Carry set if unit number bad
; No other registers altered

    LES     BP,[DPBHEAD]    ; Just in case drive isn't valid
    AND     AL,3FH          ; Mask out dirty and device bits
    CMP     AL,BYTE PTR [NUMIO]
    CMC
    JC      GOTDPB          ; Get drive A
FNDDPB:
    CMP     AL,ES:[BP.dpb_drive]
    JZ      GOTDPB          ; Carry is clear if jump executed
    LES     BP,ES:[BP.dpb_next_dpb]
    JMP     SHORT FNDDPB
GOTDPB:
    MOV     WORD PTR [THISDPB],BP
    MOV     WORD PTR [THISDPB+2],ES
    RET
GetBP   ENDP

SUBTTL SETREAD, SETWRITE -- SET UP HEADER BLOCK
PAGE
    procedure   SETREAD,NEAR
ASSUME  DS:NOTHING,ES:NOTHING

; Inputs:
;       DS:BX = Transfer Address
;       CX = Record Count
;       DX = Starting Record
;       AH = Media Byte
;       AL = Unit Code
; Function:
;       Set up the device call header at DEVCALL
; Output:
;       ES:BX Points to DEVCALL
; No other registers effected

    PUSH    DI
    PUSH    CX
    PUSH    AX
    MOV     CL,DEVRD
SETCALLHEAD:
    MOV     AL,DRDWRHL
    PUSH    SS
    POP     ES
    MOV     DI,OFFSET DOSGROUP:DEVCALL
    STOSB                   ; length
    POP     AX
    STOSB                   ; Unit
    PUSH    AX
    MOV     AL,CL
    STOSB                   ; Command code
    XOR     AX,AX
    STOSW                   ; Status
    ADD     DI,8            ; Skip link fields
    POP     AX
    XCHG    AH,AL
    STOSB                   ; Media byte
    XCHG    AL,AH
    PUSH    AX
    MOV     AX,BX
    STOSW
    MOV     AX,DS
    STOSW                   ; Transfer addr
    POP     CX              ; Real AX
    POP     AX              ; Real CX
    STOSW                   ; Count
    XCHG    AX,DX           ; AX=Real DX, DX=real CX, CX=real AX
    STOSW                   ; Start
    XCHG    AX,CX
    XCHG    DX,CX
    POP     DI
    MOV     BX,OFFSET DOSGROUP:DEVCALL
    RET

    entry   SETWRITE
ASSUME  DS:NOTHING,ES:NOTHING

; Inputs:
;       DS:BX = Transfer Address
;       CX = Record Count
;       DX = Starting Record
;       AH = Media Byte
;       AL = Unit Code
; Function:
;       Set up the device call header at DEVCALL
; Output:
;       ES:BX Points to DEVCALL
; No other registers effected

    PUSH    DI
    PUSH    CX
    PUSH    AX
    MOV     CL,DEVWRT
    ADD     CL,[VERFLG]
    JMP     SHORT SETCALLHEAD
SETREAD ENDP

do_ext

CODE    ENDS
END
但我想在我的代码中提到DEVRD=0000 0100(即十进制4或中断04h,用于溢出)和DRDWRHL=0001 0110(即十进制22或中断16h,用于键盘输入)。在这里,我感到困惑的是,为什么我们要将(0000 0100 SHL 8)放在CH中,将(0001 0110)放在CL中。这意味着我们要将两种中断类型(04h用于溢出,16h用于键盘输入)放在计数器寄存器CX中。计数器寄存器CX在这里做什么

此处使用字长
CX
寄存器方便地编写较短的代码。
指令

MOV CX,(DEVRD SHL 8) OR DRDWRHL
相当于

MOV CL, DRDWRHL
MOV CH, DEVRD
CX
版本需要3个字节,
CL
CH
版本需要4个字节。
因为这种技术重复了很多次,所以节省了很多钱

这意味着我们试图将两种中断类型(04h用于溢出,16h用于键盘输入)放入计数器寄存器CX

事实并非如此。如果进一步查看程序,您将看到
CL
存储在变量IOCALL.REQLEN中。明确表示长度的名称。
CL
以临时方式使用的进一步证据来自这样一个事实,即在它被
AH
中的任何值(86h或87h)覆盖后不久

但我想在我的代码中提到DEVRD=0000 0100(即十进制4或中断04h,用于溢出)和DRDWRHL=0001 0110(即十进制22或中断16h,用于键盘输入)。在这里,我感到困惑的是,为什么我们要将(0000 0100 SHL 8)放在CH中,将(0001 0110)放在CL中。这意味着我们要将两种中断类型(04h用于溢出,16h用于键盘输入)放在计数器寄存器CX中。计数器寄存器CX在这里做什么

此处使用字长
CX
寄存器方便地编写较短的代码。
指令

MOV CX,(DEVRD SHL 8) OR DRDWRHL
相当于

MOV CL, DRDWRHL
MOV CH, DEVRD
CX
版本需要3个字节,
CL
CH
版本需要4个字节。
因为这种技术重复了很多次,所以节省了很多钱

这意味着我们试图将两种中断类型(04h用于溢出,16h用于键盘输入)放入计数器寄存器CX

事实并非如此。如果进一步查看程序,您将看到
CL
存储在变量IOCALL.REQLEN中。明确表示长度的名称。

进一步证明
CL
是以临时方式使用的,因为在它被
AH
中的任何值(86h或87h)覆盖后不久,亲爱的Tommyley,你的回答给我留下了深刻的印象。这就说到点子上了。但我想在我的代码中提到DEVRD=0000 0100(即十进制4或中断04h,用于溢出)和DRDWRHL=0001 0110(即十进制22或中断16h,用于键盘输入)。在这里,我感到困惑的是,为什么我们要将(0000 0100 SHL 8)放在CH中,将(0001 0110)放在CL中。这意味着我们要将两种中断类型(04h用于溢出,16h用于键盘输入)放在计数器寄存器CX中。计数器寄存器CX在这里做的是什么。我更具体地提到:这里DEVRD代表设备读,DRDWTHL代表设备读写头大小。提前谢谢。不便之处,敬请原谅。我是新来的。我把事情弄得一团糟。但我渴望解决我的问题。但我在将来会遇到堆栈溢出协议。亲爱的Tommyley你的回答给我留下了深刻的印象。这就说到点子上了。但我想在我的代码中提到DEVRD=0000 0100(即十进制4或中断04h,用于溢出)和DRDWRHL=0001 0110(即十进制22或中断16h,用于键盘输入)。在这里,我感到困惑的是,为什么我们要将(0000 0100 SHL 8)放在CH中,将(0001 0110)放在CL中。这意味着我们要将两种中断类型(04h用于溢出,16h用于键盘输入)放在计数器寄存器CX中。计数器寄存器CX在这里做的是什么。我更具体地提到:这里DEVRD代表设备读,DRDWTHL代表设备读写头大小。提前谢谢。不便之处,敬请原谅。我是新来的。我把事情弄得一团糟。但我渴望解决我的问题。但我在将来会遇到堆栈溢出协议。提前谢谢。