通过汇编中的BIOS中断获取系统时间

时间:2016-12-12 16:36:11

标签: assembly interrupt bios emu8086 systemtime

我想得到中断INT 1Ah / AH = 00h的时间(小时,分钟,秒)。我知道它在CX中保留了时钟计数的高阶部分,在DX中保留了时钟计数的低阶部分。

我搜索了它,发现以下公式将时钟计数转换为 一天中的时间:

                             Hour      = Clock / 65543 (1007h)
                             Remainder = Clock MOD 65543

                             Minutes   = Remainder / 1092 (444h)
                             Remainder = Remainder MOD 1092

                             Second    = Remainder / 18.21
                             Remainder = Remainder MOD 18.21

但我对如何使用它们很困惑,我如何从CX和DX获得时钟?我应该读一个变量吗?

2 个答案:

答案 0 :(得分:1)

请勿使用该中断,请改用INT 1Ah/02。如果您坚持,请注意Clock只是CXDX形成的32位值。将它们放入变量对你来说根本无济于事。由于您需要对其进行除法,并且DIV指令期望在DX(高)和AX(低)中分红,您只需稍微改变一下即可。尽管如此,您将在除以18.21时遇到问题。像这样的东西可以工作,但请注意常量1092也不准确。如果您运气不好(如果60恰好高于clock mod 65543,则65519可能最终只有1092,除以60就会给您mov ax, dx ; low 16 bits mov dx, cx ; high 16 bits div word [mem_65543] ; constant in memory mov [hours], ax mov ax, dx ; work with remainder xor dx, dx ; zero top bits div word [mem_1092] ; constant in memory mov [minutes], ax mov ax, [mem_100] ; constant in memory mul dx ; scale by 100 div word [mem_1821] ; constant in memory mov [seconds], ax 。 )

{{1}}

答案 1 :(得分:1)

似乎EMU8086正在模拟8254定时器0,大多数PC系统仍在模拟,这里是定时值:

    8254 channel 0 runs at 1.19318 mhz or ~ 838.0965 nsecs / cycle
    System timer interrupts every 65536 cycles ~= 54.9255 ms
    or ~ 18.20648 ticks per second
    1 ms   = 1193.18 cycles
    1 hour ~= 65543 ticks ~= 3599.9816 secs
   24 hour ~= 1573040 (hex 1800B0) ticks ~= 86399.998 secs

用于将刻度线精确转换为小时/分钟/秒(截断)的示例C代码:

    i = itick<<10;             /* itick * 1024 */
    hour = 0;
    while(i >= 67116375){
        hour++;
        i -= 67116375;
    }
    i <<= 4;                   /* itick * 16384 */
    minute = 0;
    while(i >= 17897700){
        minute++;
        i -= 17897700;
    }
    second = 0;
    while(i >= 298295){
        second++;
        i -= 298295;
    }

使用32位乘16位乘法程序,您可以乘以floor((2 ^ 32)/除数),后者只需要进行一次减法检查。

uint32_t i, tick, hour, minute, second;
/* ... */
    i = tick<<10;
    hour = (uint32_t)(((uint64_t)i*63)>>32);
    i -= hour*67116375;
    if(i >= 67116375){
        hour++;
        i -= 67116375;
    }
    i <<= 4;
    minute = (uint32_t)(((uint64_t)i*239)>>32);
    i -= minute*17897700;
    if(i >= 17897700){
        minute++;
        i -= 17897700;
    }
    second = (uint32_t)(((uint64_t)i*14398)>>32);
    i -= second*298295;
    if(i >= 298295){
        second++;
        i -= 298295;
    }

使用32乘32位乘法程序,可以消除单个减法检查:

    i = tick<<10;
    hour = (uint32_t)(((uint64_t)i*2147243323u)>>57);
    i -= hour*67116375;
    i <<= 4;
    minute = (uint32_t)(((uint64_t)i*4026081231u)>>56);
    i -= minute*17897700;
    second = (uint32_t)(((uint64_t)i*1887225577u)>>49);
    i -= second*298295;