INT 21h不适用于AH = 09h

时间:2015-04-19 21:30:53

标签: assembly x86 dos interrupt

我正在尝试编程驱动程序以在55h内提供服务。我正在尝试确保一切正常但我发现当我用INT 21h = 09h调用AH来打印字符串时,即使使用正确的偏移量,它也不会打印任何内容在DX中,我不知道这是怎么回事。在代码的其他部分,它工作正常。 这是我的代码:

codigo SEGMENT
ASSUME CS :codigo
ORG 256

inicio:
    MOV AL, DS:[83H] ;Parameters: when call with '/I' installs driver
    CMP AL, 49H
    JE inst
    CMP AL, 44H ;Parameters: when call with '/D', uninstalls
    JE desinstalar_55h
    JE rsi

    PRUEBA DB "THIS IS A TEST",0AH,'$'

rsi PROC FAR
    STI
    CMP AH, 00
    JE firm ;used to check if driver is install
    MOV CX, 0
    CMP AH, 11H
    JE codificar
volver:
    IRET
desinst:
    JE desinstalar_55h
inst: 
    CALL instalador
firm:
    CALL firma
rsi ENDP


firma PROC NEAR
    MOV AX, 0F0F0H
    RET
firma ENDP

desinstalar_55h PROC
    PUSH AX
    PUSH BX
    PUSH CX
    PUSH DS
    PUSH ES
    CALL check_driver
    CMP AX, 1
    JE no_instalado
    MOV CX, 0
    MOV DS, CX
    MOV ES, DS:[55H*4+2]
    MOV BX, ES:[2CH]
    MOV AH, 49H
    INT 21H
    MOV ES, BX
    INT 21H
    CLI
    MOV DS:[55H*4], CX
    MOV DS:[55H*4+2], CX
    STI
no_instalado:
    POP ES
    POP DS
    POP CX
    POP BX
    POP AX
    RET
desinstalar_55h ENDP


instalador PROC
    CALL check_driver
    CMP AX, 1
    JNE ya_instalado
    MOV DX, OFFSET PRUEBA
    MOV AH, 09H
    INT 21H ;here it works fine
    MOV AX, 0
    MOV ES, AX
    MOV AX, OFFSET rsi
    MOV BX, CS
    CLI
    MOV ES:[55h*4], AX
    MOV ES:[55h*4+2], BX
    STI
    MOV DX, OFFSET instalador
ya_instalado:
    INT 27H
instalador ENDP

codificar PROC
    CLD
    MOV DX, OFFSET PRUEBA
    MOV AH, 09H
    INT 21H ;here it doens't print anything
    RET
codificar ENDP

check_driver PROC
    MOV AX, 0
    MOV ES, AX
    MOV AX, OFFSET rsi
    CMP WORD PTR ES:[55H*4], 0
    JNE detectar_mi_driver
    CMP WORD PTR ES:[55H*4 + 2], 0
    JE no_driver
detectar_mi_driver:
    MOV AH, 0
    INT 55H
    CMP AX, 0F0F0H
    JE fin_check
no_driver: 
    MOV AX, 1
fin_check: RET
ENDP check_driver

codigo ENDS
END inicio

例如,在安装驱动程序的'instalador'rutine中,我调用INT 21h并且它正常工作,打印字符串。但是当我从另一个.EXE程序调用{​​{1}} = 11h的中断55h时,它应该执行rsi进程并跳转到'codificar'ruutine,它调用AH,但在这种情况下,它会执行' t打印任何内容,尽管它在INT 21h中具有相同的偏移量。谁知道为什么会这样?在此先感谢您的帮助。

编辑:我尝试用TD调试它并且工作正常,打印字符串。但是,当我从另一个程序调用{​​{1}} = 11h的中断55h时,它不会打印任何内容或只是卡住而且永远不会返回。

1 个答案:

答案 0 :(得分:2)

此计划存在几个问题。

inicio:
 MOV AL, DS:[83H] ;Parameters: when call with '/I' installs driver
 CMP AL, 49H
 JE inst
 CMP AL, 44H ;Parameters: when call with '/D', uninstalls
 JE desinstalar_55h
 JE rsi

 PRUEBA DB "THIS IS A TEST",0AH,'$'

在前面的代码段中,JE rsi没用,应该用程序终止替换。您可以使用RET,因为该程序是.COM

rsi PROC FAR
 STI
 CMP AH, 00
 JE firm ;used to check if driver is install
 MOV CX, 0
 CMP AH, 11H
 JNE volver      <------------ codificar is a routine that ends with
 CALL codificar  <------------ a mere RET so call it (don't jump to it!)
volver:          <------------ and fall through in the IRET.
 IRET
;;;;desinst:              \
;;;; JE desinstalar_55h   |  Move this code outside the proc!!!
;;;;inst:                 |  Here it has no sense.
;;;; CALL instalador      /
firm:
 CALL firma
 IRET         <-- Add this because the RETF provided by ENDP is not enough!
rsi ENDP

rsi 程序遇到的问题最多。您已将其声明为FAR PROC,但实际上它是一个中断处理程序,因此它的所有出口都应该使用IRET指令。

instalador PROC
 CALL check_driver
 CMP AX, 1
 JNE ya_instalado

在标签 ya_instalado ,您有终止并保持常驻电话但是检查表明您已经安装了!通过

解决这个问题
 int 27h
ya_instalado:
 int 20h

最后但最明显的问题在于打印程序。从执行.COM调用时,DS寄存器由DOS设置。从中断处理程序55h中调用时,您必须手动设置DS。只需从CS复制它。你也不需要CLD指令。因为这毕竟是一个中断处理程序,所以你应该保留寄存器。

codificar PROC
 ;;;;CLD
 PUSH AX
 PUSH DX
 PUSH DS
 PUSH CS
 POP DS
 MOV DX, OFFSET PRUEBA
 MOV AH, 09H
 INT 21H
 POP DS
 POP DX
 POP AX
 RET
codificar ENDP