无论CPU的时钟速度如何,我都希望暂停执行大约0.1秒 . 代码应该直接从引导设备运行,因此不应该使用DOS中断 .
我目前正在使用 int 15h
,但这似乎与我正在用PIT的通道2进行调制的嘟嘟声相冲突 . 我听说过 Channels 0,但我不清楚如何设置它 .
准确性并不重要,但它应该以相同的速度在旧的和现代的计算机上运行 . 因此,循环指令不是一种选择 .
哔声代码和睡眠只是一堆用于改变频率和打开和关闭扬声器的宏 . 如果我在 beepoff
之前呼叫睡眠,哔声似乎不会停止 .
以下是蜂鸣声宏:
%macro beepinit 0
mov al, 182
out 43h, al
%endmacro
%macro beepfreq 0
out 42h, al
mov al, ah
out 42h, al
%endmacro
%macro beepon 0
in al, 61h
or al, 00000011b
out 61h, al
%endmacro
%macro beepoff 0
in al, 61h
and al, 11111100b
out 61h, al
%endmacro
和睡眠一:
%macro sleep 2
push dx
mov ah, 86h
mov cx, %1
mov dx, %2
int 15h
pop dx
%endmacro
我正在使用NASM汇编程序 .
这不是How can I create a sleep function in 16bit MASM Assembly x86?的副本,因为这个是用于Windows或DOS之外的裸机装配 .
1 回答
可编程间隔定时器是可行的方法 . 如果您只处理较新的系统,请查看HPET . 对于PIT,有几点需要了解 . 首先,要设置它,您需要使用端口0x43作为控制/命令端口来配置通道零计时器 . 我们要发送的字节是位映射字段:
通道将被清除以选择通道零 .
RW模型可以是1-LSB,2-MSB或3-LSB,然后是MSB . 我们希望两个位都打开(位模式为3,011),因为我们需要发送一个16位值(LSB然后是MSB)
对于通道模式,我们需要方波 . 这是3(011)的位模式
我们想为计数器发送一个16位除数,而不是BCD值,因此清除最低位 .
这给了我们:000110110二进制或0x36十六进制 . 现在我们设置它:
此时,您需要决定是否要对中断做出反应(IRQ 0)或只是想读取定时器 . 我将指向OSDev上的this excellent reference,它在示例代码上都有很好的写作 .