INT 21h 不适用于 AH = 09h

INT 21h is not working with AH = 09h

我正在尝试编写一个驱动程序以在 55 小时内提供服务。我正在尝试确保一切正常,但我发现当我用 AH = 09h 调用 INT 21h 来打印字符串时,它不会打印任何内容,即使偏移量正确在 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' 例程中,我调用了 INT 21h,它工作正常,打印了字符串。但是当我从另一个 .EXE 程序用 AH = 11h 调用中断 55h 时,它应该执行 rsi 进程并跳转到 'codificar' 例程,它调用 INT 21h,但在这种情况下,它不打印任何东西,尽管它在 DX 中具有相同的偏移量。任何人都知道为什么会这样?预先感谢您的帮助。

编辑: 我尝试用 TD 调试它并且工作正常,打印字符串。但是,当我从另一个程序用 AH = 11h 调用中断 55h 时,它不打印任何东西或者只是卡住了并且从不 returns.

这个程序存在一些问题。

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