2

我是 x86 汇编的初学者。我已经编译了一个小型操作系统(用 nasm 编译到软盘上),但我遇到了一些麻烦。该操作系统旨在打开 Caps、Scroll 和 Num Lock,然后等待半秒,然后关闭它们,然后等待半秒。然后它重复。

问题出在线路clisti. 这应该启用以确保原子性,因此时间对于Wait_Clk_Ticks. 当这些线被放入程序时,灯会亮起,但仅此而已。当他们不在程序中时,灯会按应有的方式闪烁。这段代码有什么问题?

jmp代码中的函数是否会Wait_Clk_Ticks导致中断?我被告知clisti用于禁用硬件中断。是否jmp会导致硬件中断?

代码:

; blinklights.asm



[BITS 16]
[ORG 0x7C00]

jmp Code_Start


Switch_Kbd_Leds:

    push dx     ; Store current values.
    push ax

    mov dx, 60h ; '60h' is the 'kbd' port value.
    mov al, 0EDh    ; '0EDh' is 'set/reset leds' function.
    out dx, al  ; Then output to the port.

    pop ax      ; Get the setting from the stack.
    out dx, al  ; Output this data to the port.

    pop dx      ; Restore 'dx'.
    ret     ; Return.

Wait_Clk_Ticks:


    cli

    mov  ax, 0
    mov  ds, ax
    mov  bx, [46Ch]
    WaitForAnotherChange:
    NoChange:
    mov  ax, [46Ch]
    cmp  ax, bx
    je   NoChange
    mov  bx, ax
    loop WaitForAnotherChange

    sti

    ret     ; Return.

Code_Start:
    mov al, 00000111b
    call Switch_Kbd_Leds

    mov cx, 9
    call Wait_Clk_Ticks

    mov al, 00000000b
    call Switch_Kbd_Leds

    mov cx, 9
    call Wait_Clk_Ticks

    jmp Code_Start



End:
    jmp $       ; Run this line over and over again- stops excecution.

times 510-($-$$) db 0   ; Fill the rest of the 512 byte sector with zeros
dw 0xAA55       ; Boot magic number

我在 IBM 8307 上使用 USB 键盘运行此代码。

谢谢你的帮助 :)

4

2 回答 2

2

你不觉得cli也禁用了时钟中断,定时器就停止了吗?

于 2013-06-11T07:00:02.530 回答
1

不,jmp不会导致中断...但是计时器滴答会...或者会,如果您没有关闭它们!

这可能超出了您的需要,但我记得它曾经有效。快乐开机!

; nasm -f bin -o kblites.com  kblites.asm

org 100h

section .text

    mov al, 4          ; set a starting mask - caps-lock
go:
    call set_lites
    jc .error

    push ax
    mov ah, 1           ; get a key and echo it
    int 21h             ; (just to demo that caps-lock
    cmp al, 1Bh         ; is working independent of the leds)
    pop ax

    jz .exit            ; quit if ESC hit

    shr al, 1           ; else change mask and go again
    jnz go
    mov al, 4
    jmp short go

.error:
    mov al, 'E'
    int 29h

.exit:
    mov ah, 4Ch
    int 21h
;--------------


;-------------------------------
; set_lites
; expects - a mask to set the keyboard leds in al
; bit 0 - scroll-lock, bit 1 - num-lock, bit 2 - caps-lock
; other bits should be 0
; returns - carry set on error
;-------------------------------
set_lites:
    push cx            ; save caller's reg
    push ax            ; al has our desired led mask
;    xor cx, cx         ; retry counter, so we don't loop forever
    or cx, byte -1
.top:
    in al, 64h         ; get keyboard status byte
    test al, 3         ; wait until we're okay to write
    jz .good
    in al, 60h         ; flush any input waiting
    dec cx
    jz .got_ack
    jmp short .top     ; try again
.good:
    mov al, 0EDh       ; set led command
    out 60h, al
.get_ack:
    in al, 60h         ; wait for acknowledgement
    cmp al, 0FAh       ; curiously, this isn't neccessary
    jz .got_ack        ; when running in a "dos-box", but
    dec cx             ; "real dos" requires it (?).
    jz .got_ack
    jmp short .get_ack
.got_ack:              ; bail out if we never get it
    pop ax             ; get our led mask back
    out 60h, al        ; set 'em!
    cmp cx, byte 1     ; set carry if retry-counter ran out
    pop cx             ; restore caller's reg
    ret
;---------------

于 2013-06-11T09:20:47.853 回答