问题
I am an beginner in x86 assembly. I have compiled a small operating system (compiled with nasm onto a floppy disk), and I am having some trouble with it. This operating sysem is designed to turn on Caps, Scroll, and Num Lock, then wait for half of a second, then turn them off, then wait half a second. Then it repeats.
The problem is at the lines cli and sti. This should be enabled to ensure atomicity, so the timing is correct for Wait_Clk_Ticks. When these lines are put into the program, the lights turn on, but that is all. When they are not in the program, the lights blink on and off as they should. What is wrong with this code?
Are the jmp functions in the Wait_Clk_Ticks code causing an interrupt? I am told that cli and sti are used to disable hardware interrupts. Does jmp cause a hardware interrupt?
Code:
; 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
I am running this code with a USB keyboard on an IBM 8307.
Thanks for your help :)
回答1:
Don't you think cli also disables the clock interrupt, and the timer stops?
回答2:
No, the jmp doesn't cause an interrupt... but the timer tick does... or would, if you didn't turn 'em off!
This is probably more than you need, but as I recall it used to work. Happy bootin'!
; 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
;---------------
来源:https://stackoverflow.com/questions/17037142/cli-and-sti-are-not-working