Reputation: 57
I'm trying to program a driver to provide services in 55h. I'm making some tries to be sure everything works but I've found that when I call INT 21h
with AH
= 09h to print a string, it doesn't print anything, even with the right offset in DX
, and I don't have any idea how this can be. In other sections of the code, it works fine.
Here's my code:
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
For example, inside 'instalador' rutine, which install the driver, I make a call to INT 21h
and it works fine, printing the string. But when I call the interruption 55h with AH
= 11h from another .EXE program, it should execute rsi process and jump to 'codificar' rutine, which calls INT 21h
, but in this case, it doens't print anything, although it has the same offset in DX
. Anyone knows why this can be? Thanks in advance for your help.
EDIT: I've tried to debugged it with TD and works fine, prints the string. However, when I call the interruption 55h with AH
= 11h from another program, it doesn't print anything or just got stuck and never returns.
Upvotes: 2
Views: 1289
Reputation: 39676
Several problems exist in this program.
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,'$'
In the previous code snippet the JE rsi
is useless and should be replaced by a program termination. You can use RET
because the program is a .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
The rsi procedure has the most problems. You have declared it to be a FAR PROC but in fact it is an interrupt handler and thus all of its exits should use the IRET
instruction.
instalador PROC
CALL check_driver
CMP AX, 1
JNE ya_instalado
At the label ya_instalado you have a terminate and stay resident call BUT the check made it clear that you are already installed! Solve this via
int 27h
ya_instalado:
int 20h
The last but most visible problem sits in the printing routine. When called from the executing .COM the DS register is setup by DOS. When called from within the interrupt handler 55h you have to setup DS manually. Just copy it from CS. Also you don't need the CLD instruction. And since this is after all an interrupt handler you are supposed to preserve registers.
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
Upvotes: 2