4

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.
Michael Petch
  • 46,082
  • 8
  • 107
  • 198
  • (Welcome to SO! (Turkish keyboard notwithstanding(ES:DI))) Please present the results of the code shown. (Try using a spelling checker to avoid having `erors` distract from the substance of your posts.) – greybeard Dec 16 '17 at 16:33
  • What errors exactly? Copy/paste them into the question and make this a [mcve]. The most obvious thing is that emu8086 probably only accepts ASCII register names, like `ES:DI`, not UTF-8 Turkish characters like `İ ` (well spotted, @greybeard). – Peter Cordes Dec 16 '17 at 16:51
  • 2
    In EMU8086, syntax is much like MASM. Your code seems to use NASM syntax. In MASM/EMU8086 you need to use `byte ptr` instead of `byte` and the segment prefix needs to be outside the square brackets.The proper MASM/EMU8086 syntax would be `or byte ptr es:[di],40h` – Michael Petch Dec 16 '17 at 16:59
  • Oh I didn't look at whether your logic works (or if this eve works with EMU8086), only answering the immediate question as to why that one line won't even assemble.This is in response to a now deleted comment ;-) – Michael Petch Dec 16 '17 at 21:08
  • thank you for your comment... @MichaelPetch I used or byte ptr [di],40h .. There isn't error but I can't see light. (23) wrong parameters: OR byte [es:di],40h (23) probably it's an undefined var: byte [es:di] – Denizcan Demir Dec 16 '17 at 21:12

2 Answers2

3

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
; - - - - - - - - - - - - - - - - - - - - - - -
Sep Roland
  • 33,889
  • 7
  • 43
  • 76
  • 1
    The question is about EMU8086 and this method won't work. Besides lighting the LED not working, EMU8086 has no concept of local labels. So it sees `.1`, `.2` as global labels and will fail because of the duplicates of course. – Michael Petch Dec 17 '17 at 22:06
  • 2
    @MichaelPetch I had my doubts about emu8086 given that it's vastly inferior to DOSBox. I'll change the local labels though so people can give it a try and find out for themselves too. – Sep Roland Dec 17 '17 at 22:14
  • No problem, despite that I upvoted. Was still a good answer for the general case of MASM/TASM and appropriate emulation/real hardware. – Michael Petch Dec 17 '17 at 22:16
0

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.