Kim*_*ürs 5 assembly sleep 16-bit
无论CPU的时钟速度如何,我都希望暂停执行大约0.1秒.代码应该直接从引导设备运行,因此不应该使用DOS中断.
我正在使用int 15h,但这似乎与我用PIT的通道2进行调制的嘟嘟声相冲突.我听说过频道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
Run Code Online (Sandbox Code Playgroud)
和睡眠一:
%macro sleep 2
push dx
mov ah, 86h
mov cx, %1
mov dx, %2
int 15h
pop dx
%endmacro
Run Code Online (Sandbox Code Playgroud)
我正在使用NASM汇编程序.
这不是重复如何在16位MASM Assembly x86中创建睡眠功能?,因为这个是用于Windows或DOS之外的裸机组装.
可编程间隔定时器是最佳选择。如果您只处理较新的系统,请考虑 HPET。对于 PIT,有一些事情需要了解。首先,要进行设置,您需要使用端口 0x43 作为控制/命令端口来配置通道零定时器。我们要发送的字节有一个位映射字段:
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
+----------------------------------------------+
| Channel | RW Mode | Channel Mode | BCD?|
+----------------------------------------------+
Run Code Online (Sandbox Code Playgroud)
通道将被清除以选择通道零。
RW 模型可以是 1-LSB、2-MSB 或 3-LSB 后跟 MSB。我们希望这两个位都打开(位模式为 3, 011),因为我们需要发送 16 位值(LSB 然后 MSB)
对于通道模式,我们需要方波。这是 3 (011) 的位模式
我们想要发送计数器的 16 位除数,而不是 BCD 值,因此最低位被清除。
这给了我们:二进制的 000110110 或十六进制的 0x36。现在我们进行设置:
mov al, 0x36 ; 0x36 from our work above
out 0x43, al ; Send that byte to the control port
mov ax, 11931 ; The timer ticks at 1193182. 100hz would be 1193182/11931
out 0x40, al ; send low byte
out 0x40, ah ; send high byte
Run Code Online (Sandbox Code Playgroud)
此时,您需要决定是否要对中断 (IRQ 0) 做出反应,或者只是想读取计时器。我将向您推荐关于 OSDev 的这篇优秀参考资料,其中对两者都有精彩的文章和示例代码。