Reputation: 41
how can I turn on caps lock's light in keyboard with assembly emu8086
is it true ? Any other solution can you say it
data segment
; add your data here!
pkey db "press any key...$"
ends
stack segment
dw 128 dup(0)
ends
code segment
start:
; set segment registers:
mov ax, data
mov ds, ax
mov es, ax
mov ax,0040h
mov es,ax
mov ax,0017h
mov di,ax
or byte [es:di],40h ; why are there erors -> ES:Dİ
mov ax, 4c00h ; exit to operating system.
int 21h
ends
end start ; set entry point and stop the assembler.
Upvotes: 4
Views: 1933
Reputation: 328
I make use of several emulators. For msdos I employ dosbox and pcem. My problem was that sometimes caps lock is not synchronized between host and virtual machine. What I needed was a program that changes caps lock only inside virtual machine. From the question code and with tasm assembler I wrote this:
.286
.MODEL TINY
.CODE
ORG 100H
ENTRADA:
MOV AX, 0040H
MOV DS, AX
XOR BYTE PTR DS:[0017H], 40H
MOV AX, 4C00H
INT 21H
END ENTRADA
If I compile this code, I get a .com file of 15 bytes length and it works on dosbox and pcem.
Thanks for reading.
Upvotes: 0
Reputation: 39176
Turning one or more of the keyboard leds on or off is not a simple matter of writing a single value in one of the BIOS variables!
It involves outputting to several of the keyboard's ports as well as updating several BIOS variables so that BIOS and DOS can still know what the status of these indicators is.
Next program does all that is needed to set the CapsLock indicator.
The program was tested and works perfectly under a true DOS like DOS 6.20.
If the program outputs "0" all went well, if you see a "1" then the indicator could not be set.
What will happen under emulation remains to be seen. DOSBox eg. changes the CapsLock condition but refuses to light the relevant led.
ORG 256 ;Create .COM program
push ds
mov ax, 0040h ;BIOS data segment
mov ds, ax
mov dl, 00000100b ;Set CapsLock
call SetIndicators ; -> CF
pop ds
mov dl, "0"
adc dl, 0
mov ah, 02h ;Display character
int 21h
mov ah, 01h ;Wait for a key
int 21h
int 20h ;Terminate
; - - - - - - - - - - - - - - - - - - - - - - -
; IN (dl) OUT (CF)
SetIndicators:
test byte ptr [0097h], 01000000b
stc
jnz SetIndicators_3 ;Update in progress -> CF=1
push ax
push cx
push dx
and dl, 00000111b
mov al, dl
mov cl, 4
shl al, cl
and byte ptr [0017h], 10001111b
or [0017h], al
and byte ptr [0097h], 11111000b
or [0097h], dl
mov al, 0EDh ;Command to set KB leds
call SendToPort60
test byte ptr [0097h], 10000000b ;Was command acknowledged ?
jnz SetIndicators_1 ;No
mov al, dl
call SendToPort60
test byte ptr [0097h], 10000000b ;Was command acknowledged ?
jz SetIndicators_2 ;Yes
SetIndicators_1:
mov al, 0F4h ;Command to enable KB
call SendToPort60
SetIndicators_2:
and byte ptr [0097h], 00111111b ;OK -> CF=0
pop dx
pop cx
pop ax
SetIndicators_3:
ret
; - - - - - - - - - - - - - - - - - - - - - - -
; IN (IF=0) OUT ()
WaitForEmptyInbuffer:
push ax
push cx
mov cx, 03E3h
WaitForEmptyInbuffer_1:
in al, 61h
and al, 00010000b ;Toggles each refresh request
cmp al, ah
je WaitForEmptyInbuffer_1
mov ah, al
in al, 64h
test al, 00000010b ;Input buffer is full
loopnz WaitForEmptyInbuffer_1
pop cx
pop ax
ret
; - - - - - - - - - - - - - - - - - - - - - - -
; IN (al,ds=0040h) OUT ()
SendToPort60:
push ax
push bx
push cx
mov bh, al
mov bl, 3
SendToPort60_1:
cli
and byte ptr [0097h], 01001111b
call WaitForEmptyInbuffer
mov al, bh
out 60h, al ;This also enables KB !!!
sti ;STI is essential because FAh/
mov cx, 03E3h ; FEh arrive thru interrupt 9
SendToPort60_2:
test byte ptr [0097h], 00010000b ;Was aknowledged ?
jnz SendToPort60_4 ;Yes
test byte ptr [0097h], 00100000b ;Needs resending ?
jnz SendToPort60_3 ;Yes
in al, 61h
and al, 00010000b ;Toggles each refresh request
cmp al, ah
je SendToPort60_2
mov ah, al
loop SendToPort60_2
SendToPort60_3:
dec bl
jnz SendToPort60_1
or byte ptr [0097h], 10000000b ;Command was NOT aknowledged or
SendToPort60_4:
pop cx ; ... KB kept asking to resend!
pop bx
pop ax
cli
ret
; - - - - - - - - - - - - - - - - - - - - - - -
Upvotes: 3