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
我正在尝试编写一个驱动程序以在 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