Page 1 of 1

Can you spot the error???

Posted: Fri Feb 19, 2010 9:45 am
by DLBuunk
Can you spot the error I made in my timer code? It took me two days to find it.

Code: Select all

IRQ0:
        push    ax
        mov     byte [.flag],01h
        mov     al,20h
        out     20h,al
        pop     ax
        iret
.flag:  db      00h

timer:   ;cx is number of 18.2 Hz ticks to wait
        hlt
        cmp     byte [IRQ0.flag],01h
        jne     timer
        mov     byte [IRQ0.flag],01h
        dec     cx
        cmp     cx,00h
        jne     timer
        ret
When I test it with the following code it appears to work fine:

Code: Select all

timertest:   ;print 1 '!' per second to the screen (infinite loop)
        mov     cx,12h
        call    timer
        mov    ax,0E21h
        int     10h
        jmp     timertest

Re: Can you spot the error???

Posted: Fri Feb 19, 2010 11:18 am
by Gigasoft
Well, you're setting IRQ0.flag to 1, which it already is, instead of some other value. You also ought to know that the DEC instruction updates ZF, and that the LOOP instruction performs the same function as DEC CX / JNZ.

Re: Can you spot the error???

Posted: Fri Feb 19, 2010 5:39 pm
by Combuster
Four seconds. Memory operand with undefined segment register contents. (line 3)

Re: Can you spot the error???

Posted: Sat Feb 20, 2010 12:07 am
by bitshifter
A more elegant way...

Code: Select all

IRQ0:
    inc [.ticks]
    iret
  .ticks dw 0

timer: ; cx = number of ticks to wait...
    push cx
    add cx,[IRQ0.ticks]
  .wait:
    cmp [IRQ0.ticks],cx
    jl .wait
    call print
    pop cx
    ret

Re: Can you spot the error???

Posted: Sat Feb 20, 2010 4:04 am
by Brendan
Hi,
Combuster wrote:Four seconds. Memory operand with undefined segment register contents. (line 3)
That may be intentional. I do my OS like that - data segment registers treated as constants, with some tricky "general protection fault" handler code to reset them if some idiot changes them (and no hope or desire to support Virtual8086). Segment register loads are slow... ;)
bitshifter wrote:A more elegant way...
A more buggy way (you forgot to send the EOI to the PIC, there's "roll over" bugs, and you don't HLT to save power). 8)


Cheers,

Brendan

Re: Can you spot the error???

Posted: Sat Feb 20, 2010 6:02 am
by Owen
Isn't DS going to change every time you enter user space anyway? Or is your OS x86_64 only? (I can't ascertain with the OP's but I'd guess not)

Particularly on i386 I'd be wary about using wrong segment registers since any API I'd define for x86 would have LDT support (Some things require the ability to create their own segments - an example is WINE)

Re: Can you spot the error???

Posted: Sat Feb 20, 2010 6:14 am
by Combuster
Brendan wrote:Hi,
Combuster wrote:Four seconds. Memory operand with undefined segment register contents. (line 3)
That may be intentional. I do my OS like that - data segment registers treated as constants, with some tricky "general protection fault" handler code to reset them if some idiot changes them (and no hope or desire to support Virtual8086). Segment register loads are slow... ;)
Given the use of 16-bits registers throughout, including as arguments to an interrupt call within the intel-reserved range (another potential bug), I assumed it was written for real mode.

And who said the bug was not a GPF? :mrgreen:

Re: Can you spot the error???

Posted: Sat Feb 20, 2010 6:34 am
by Owen
Combuster wrote:
Brendan wrote:Hi,
Combuster wrote:Four seconds. Memory operand with undefined segment register contents. (line 3)
That may be intentional. I do my OS like that - data segment registers treated as constants, with some tricky "general protection fault" handler code to reset them if some idiot changes them (and no hope or desire to support Virtual8086). Segment register loads are slow... ;)
Given the use of 16-bits registers throughout, including as arguments to an interrupt call within the intel-reserved range (another potential bug), I assumed it was written for real mode.

And who said the bug was not a GPF? :mrgreen:
It could be 16-bit protected mode...

(Yeah, right...)

Re: Can you spot the error???

Posted: Sat Feb 20, 2010 11:53 am
by Gigasoft
bitshifter wrote:A more elegant way...
This has the same lack of CS: override as above, and it also introduces 3 new problems. It doesn't perform an EOI, it doesn't conserve energy, and it has an integer overflow problem. Here's a more correct version that waits for an exact number of 18.2ths of a second:

Code: Select all

IRQ0:
        push    ax
        mov     byte [cs:.flag],01h
        mov     al,20h
        out     20h,al
        pop     ax
        iret
.flag:  db      00h

timer:   ;cx is number of 18.2 Hz ticks to wait
        mov al,34h ; Reset timer
        out 43h,al
        mov al,0
        out 40h,al
        out 40h,al
.tmr2:
        mov [IRQ0.flag],0
.tmr1:
        hlt
        cmp byte [IRQ0.flag],0
        jz     .tmr1
        loop     .tmr2
        ret