Hey folks,
I'm assembling a small TSR for DOS (MS-DOS is v6.22) and my TSR code works flawlessly ONLY IF I assemble my source (MASM 6.11) and then install by typing the name of the .com file. If I simply boot (warm or cold), skip the assembly process, and just install the .com as it was last assembled, the code works up to the point where I check the keyboard port. It's like the keyboard reading code isn't being observed properly. Here's some of the pertinent code in question:
CA_Wait: ; Wait Loop
call KBS_Service
test BYTE PTR CS:[New_08 + 4], 1
jnz Return
mov DX, 379h
in AL, DX
and AL, 60h
jz CA_Wait ; Loop
KBS_Service:
pushf
push AX
push DX
push ES
in AL, 20h
test AL, 2
jz KBS_End
in AL, 60h
cmp AL, 1
jne Esc_Key_No
or BYTE PTR CS:[New_08 + 4], 1
Esc_Key_No:
mov AX,0040h
mov ES, AX
mov AL, ES:[001Ch]
mov ES:[001Ah], AL
mov AL,20h ;Clear interrupt controller
out 20h,AL
out 0Ah,AL
and ES:[0017h], 0F0h
KBS_End:
pop ES
pop DX
pop AX
popf
ret
Basically, the wait loop is waiting on either signals from the parallel port, or the Esc key from the keyboard to exit the loop. Just before this wait loop is entered, the keyboard interrupt mask is applied on port 21h, bit 1, so that no keyboard interrupt is processed. It gets re-enabled later on. Like I said, this works great as long as I assemble just before installing--as if the assembler running is somehow creating a more cohesive/conducive environment for this code. Anyone have thoughts on this behavior? Hopefully I've made it clear what's going on. Thanks for the help!
John
I'd say, as a first guess, that this has nothing at all to do with the assembler, and everything to do with the state of the keyboard port (or the interrupt controller) when you're reading them.
Not sure what exactly you're doing by reading the interrupt controller (port 20h) before looking for a keystroke: what's the logic here? Are you first looking for a pending interrupt, as if a key had been pressed? That might be the problem, or at least part of it.
Quote"Not sure what exactly you're doing by reading the interrupt controller (port 20h) before looking for a keystroke: what's the logic here? Are you first looking for a pending interrupt, as if a key had been pressed? That might be the problem, or at least part of it."
Quote from: jejump on Today at 01:11:22 AM"Just before this wait loop is entered, the keyboard interrupt mask is applied on port 21h, bit 1, so that no keyboard interrupt is processed. It gets re-enabled later on."
So, unless I don't understand something about disabling keyboard interrupts, I assume given the above statement, the only way to know if a character is waiting is to poll the interrupt line (port 20h bit 1) since no interrupt is being processed for the keyboard. I stole this code and method from a different project of mine where disabling the keyboard from interrupt processing was more necessary than it is with this recent project. I could possibly allow interrupt processing for the keyboard and all will be well. That might be how I fix it. I'm just curious at this point, why this doesn't work regardless of whether I run the assembler just before or whenever before.
Thanks for the response.
Jj
If you are polling the keyboard you shouldn't send EOI, this should only be sent by an ISR.
What's wrong with using INT 16h, AH=11h?
Quote from: jejump on Today at 01:11:22 AMBasically, the wait loop is waiting on either signals from the parallel port, or the Esc key from the keyboard to exit the loop. Just before this wait loop is entered, the keyboard interrupt mask is applied on port 21h, bit 1, so that no keyboard interrupt is processed.
That's good and needed for polling.
KBS_Service:
pushf
push AX
push DX
push ES
in AL, 20h
test AL, 2
jz KBS_End
As NoCForMe already pointed out, what's expected by reading port 20h here?
in AL, 60h
cmp AL, 1
If kbd is polled, one should not unconditionally read port 60h, but first check if a byte is actually ready to be read:
in al, 64h
test al, 01h ; input buffer full?
jz nokey
mov ah, al
in al, 60h
test ah, 20h ; is it input from PS/2 mouse?
jnz nokeyps2
And input from PS/2 mice may also appear at port 60h, so better filter that as well.
mov AL,20h ;Clear interrupt controller
out 20h,AL
out 0Ah,AL
Already mentioned by sinsi: don't sent EOI to PIC if kbd is polled. And writing to port 0Ah - that's the ISA DMA controller!!!
Excellent information here! I'm going to change the method of how I detect a key press to reading port 64h. I wondered about the mouse hardware maybe causing conflict even though I don't have a mouse driver loaded. Thanks for the tips!