我想得到中断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获得时钟?我应该读一个变量吗?
答案 0 :(得分:1)
请勿使用该中断,请改用INT 1Ah/02
。如果您坚持,请注意Clock
只是CX
和DX
形成的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;