All off topic discussions go here. Everything from the funny thing your cat did to your favorite tv shows. Non-programming computer questions are ok too.
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:
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.
Four seconds. Memory operand with undefined segment register contents. (line 3)
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
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).
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
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)
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?
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
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.
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:
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