4

I need to get system uptime since last boot using C.

Target OS is MS DOS.

I tried time(), ftime() but they are relative to Jan 1,1970 00:00:00.

Can anybody suggest some solution?

Thanks in advance.

8
  • 2
    There is probably no standard c function for it, but have a look at how it is done here: nikkhokkho.sourceforge.net/static.php?page=UPTIME
    – Ctx
    Commented Jun 23, 2017 at 8:50
  • The MS DOS system timer interrupt is called at 18.2065 Hz and increments the 32-bit counter at 0040:006C which is the number of ticks since power up. When the count reaches 24 hours, it is cleared and the byte value at 0040:0070 is incremented. Commented Jun 23, 2017 at 9:04
  • You could research int 1Ah function 00h Get Clock Counter, which I think has the side effect of clearing the midnight flag. Commented Jun 23, 2017 at 9:22
  • You may get the time at boot time and then, when you need the uptime, you may read again the time, then you may use the function difftime() to get the uptime value. cplusplus.com/reference/ctime/difftime Commented Jun 23, 2017 at 9:40
  • If your target platform is *nix take a look at uptime.c from procps Commented Jun 23, 2017 at 9:45

1 Answer 1

4

To read the system time on MS-DOS, you can call INT 1a,0, e.g. like this (GNU syntax):

unsigned short cx, dx;
__asm__ (
    "mov    $0, %%ah    \n\t"
    "int    $0x1a       \n\t"
    : "=c" (cx), "=d" (dx)
    :
    : "ax"
    );
time_t time = cx;
time <<= 16;
time |= dx;
time = (time_t) ((double)time / 18.2065);

This is probably your best bet. If nobody has set this time using INT 1a,1, you will get the seconds since boot.

Note this only counts up to 24 hours, if you need longer periods of time, you have to call this regularly and pay attention to the "midnight flag" in al.

Add another output variable in this case, increment a day counter whenever you see al non-zero and just add days * 86400 to the final result, rough outline:

unsigned short ax, cx, dx;
static unsigned days = 0;
__asm__ (
    "mov    $0, %%ah    \n\t"
    "int    $0x1a       \n\t"
    : "=a" (ax), "=c" (cx), "=d" (dx)
    );
if (ax & 0xff) ++days;
time_t time = cx;
time <<= 16;
time |= dx;
time = (time_t) ((double)time / 18.2065);
time += days * 86400;

I found some additional info that might be useful here:

The second problem comes in because of how BIOS int 0x1A operates. Whenever you call this function to retrieve the system time (the current timer tick value) it also returns the current MIDNIGHT flag and RESETS THE FLAG. But since the BIOS function doesn't update the DOS date, the next time you ask for the date, it will not be updated correctly. DOS is aware of the behavior, so when you call any DOS function, the MIDNIGHT flag is maintained correctly. If you call BIOS int 0x1A yourself, you MUST check the MIDNIGHT flag value and turn it back on if it was set.

So, in short, if you need MS-DOS to maintain a correct date while your program is running, you have to do additional work (like restoring the flag manually and calling INT 21,2A each time it was found)

10
  • What if uptime is more than 24 hours? 666 days, for example? Commented Jun 23, 2017 at 10:04
  • @AndrejsCainikovs just edited, but without example code because there are different ways to arrange the regular calls.
    – user2371524
    Commented Jun 23, 2017 at 10:06
  • We are talking non-protect mode DOS here, it was lucky to make it over night. And unless you had dual 8-inch floppies, there was always a risk of crash on a disk read error when swapping the data and system disks in-and-out so your code could complete... 8088 and 8086 machines were good machines, came complete with sneaker-net right out of the box... Commented Jun 23, 2017 at 10:14
  • Just for the sake of completeness, the second example should account for days if called often enough :) (but code is untested)
    – user2371524
    Commented Jun 23, 2017 at 10:16
  • While this is very hacky, I do agree this is probably the least painful way to get up-time (calculate, to be more precise), since MS-DOS does not give you this functionality. Another approach would be get the up-time from peripherals. For example, all modern hard drives support ATAPI and you're able to read statistics from your drive (power-on hours) using that protocol. But this is pain the ass. Commented Jun 23, 2017 at 10:20

Not the answer you're looking for? Browse other questions tagged or ask your own question.