cassemblyx86x86-16dos

How much of this is needed to read ticks from the BIOS (8086)?


I have the following function (C with assembly) that reads BIOS ticks:

static clock_t clock(void);
#pragma aux clock = \
"pushf" \
"push ds" \
"cli" \
"mov ax, 0x0040" \
"mov ds, ax" \
"mov bx, 0x006C" \
"mov ax, [bx]" \
"sti" \
"pop ds" \
"popf" \
parm [ ax ] \
modify [ ax bx ];

This works, but how much of it is necessary? Can someone help me code golf this a bit? I'm working with 8086 (tiny memory model), and I'm not sure if I need to pushf and popf or cli and sti before reading the value. I'd also appreciate if it's possible to reduce the number operations. I know nothing about far pointers and fudged this together (first time).


Solution

  • You just need to read a word from address 0000:046c to get the low 16 bits of the tick counter. An easy way to do this is to use a far volatile pointer:

    #include <i86.h>
    
    #define ticks (*(volatile unsigned short __far *)MK_FP(0x0000, 0x046c))
    

    Other equivalent addresses like 0040:006c can be used, too.

    You can then access the ticks counter as such:

    int now;
    
    now = ticks;
    

    Note that this will only give you the low 2 bytes. If you want all bytes, you'll have to disable interrupts to do an atomic read of the whole counter (or loop until convergence).

    You can also use the predefined functions clock or _bios_timeofday as indicated in the manual for this purpose.