简体   繁体   中英

how can I turn on caps lock's light in keyboard with assembly emu8086

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.

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
; - - - - - - - - - - - - - - - - - - - - - - -

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM