【问题标题】:how can I turn on caps lock's light in keyboard with assembly emu8086如何使用组件emu8086打开键盘中的大写锁定灯
【发布时间】:2017-12-16 16:10:35
【问题描述】:

如何使用组件 emu8086 打开键盘上的大写锁定灯
是真的吗?你能说其他任何解决方案吗

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.

【问题讨论】:

  • (欢迎使用 SO!(尽管有土耳其语键盘(ES:DI)))请提供所示代码的结果。 (尝试使用拼写检查器,以避免 erors 分散您帖子的内容。)
  • 究竟是什么错误?将它们复制/粘贴到问题中并将其设为minimal reproducible example。最明显的是,emu8086 可能只接受 ASCII 寄存器名称,例如 ES:DI,而不接受 UTF-8 土耳其字符,例如 İ (很明显,@greybeard)。
  • 在 EMU8086 中,语法很像 MASM。您的代码似乎使用 NASM 语法。在 MASM/EMU8086 中,您需要使用 byte ptr 而不是 byte,并且段前缀需要在方括号之外。正确的 MASM/EMU8086 语法是 or byte ptr es:[di],40h
  • 哦,我没有看你的逻辑是否有效(或者这个前夕是否适用于 EMU8086),只回答了直接的问题,即为什么那一行甚至无法组装。这是回应到现在删除的评论;-)
  • 感谢您的评论... @MichaelPetch 我使用或 byte ptr [di],40h .. 没有错误,但我看不到光。 (23) 错误参数:OR byte [es:di],40h (23) 可能是未定义的 var: byte [es:di]

标签: assembly dos x86-16 emu8086


【解决方案1】:

打开或关闭一个或多个键盘 LED 并不是在其中一个 BIOS 变量中写入单个值的简单问题!
它包括输出到几个键盘端口以及更新几个 BIOS 变量,以便 BIOS 和 DOS 仍然可以知道这些指示灯的状态。

下一个程序会执行设置 CapsLock 指示器所需的所有操作。
该程序经过测试,可在 DOS 6.20 等真正的 DOS 下完美运行。
如果程序输出“0”一切顺利,如果您看到“1”,则无法设置指标。

在仿真下会发生什么还有待观察。 DOSBox 例如。更改 CapsLock 条件但拒绝点亮相关 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
; - - - - - - - - - - - - - - - - - - - - - - -

【讨论】:

  • 问题是关于EMU8086,这个方法不行。除了点亮 LED 不工作外,EMU8086 没有本地标签的概念。所以它将.1.2 视为全局标签,当然会因为重复而失败。
  • @MichaelPetch 我对emu8086表示怀疑,因为它远不如DOSBox。不过我会更改本地标签,以便人们也可以尝试一下并自己找出答案。
  • 没问题,尽管我赞成。对于 MASM/TASM 和适当的仿真/真实硬件的一般情况,仍然是一个很好的答案。
【解决方案2】:

我使用了几个模拟器。对于 msdos,我使用 dosbox 和 pcem。我的问题是有时主机和虚拟机之间的大写锁定不同步。我需要的是一个仅在虚拟机内部更改大写锁定的程序。从问题代码和 tasm 汇编器我写了这个:

.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

如果我编译这段代码,我会得到一个 15 字节长度的 .com 文件,它适用于 dosbox 和 pcem。

感谢阅读。

【讨论】:

    猜你喜欢
    • 2011-01-15
    • 2011-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-22
    • 2014-07-21
    • 2020-08-06
    相关资源
    最近更新 更多