Windows API 里面有一个 Beep.aspx) 函数,作用是发出蜂鸣声。这个蜂鸣功能历史悠久,BIOS 的报警声就是从主板蜂鸣器里出来的,其原理是调用几乎每台机器都有的 Programmable Interval Timer (PIT)。可惜从 Windows Vista 开始,这个函数的行为变成了调用扬声器发声,而不再是使用主板蜂鸣器发声了。
如何在 Windows Vista 以上的系统里使用主板蜂鸣器发声呢?是不是必须写个 Windows 驱动呢?其实利用 WinDbg 内核调试器的功能,只需要一行代码就能搞定。下面一行代码以 800 Hz 的频率让主板蜂鸣器发声 1000 毫秒。
n 10; r $t0=800; r $t1=1000; ob 0x43 0xb6; ob 0x42 (1193180/$t0)&0xff; ob 0x42 (1193180/$t0)>>8; ob 0x61 3; .sleep $t1; ob 0x61 0
使用方法:
- 下载安装 WinDbg
- 打开内核调试。管理员权限运行
bcdedit /debug on
,重启。 - 管理员权限打开 WinDbg,File->Kernel Debug,选择 “Local” 选项卡,确定。不出意外的话,就会进入 kernel debug session。
- 输入这段代码,如果你的主板蜂鸣器正常的话,应该就能听到蜂鸣声了。(可惜,截图里不带声音)
原理:
n 10; 设置十进制,默认 WinDbg 是 16 进制 r $t0=800; 设置 WinDbg 内部寄存器 t0 为 800,表示发声频率 r $t1=1000; 设置 WinDbg 内部寄存器 t1 为 1000,表示发声时长(毫秒) ob 0x43 0xb6; 设置 PIT 输出到主板蜂鸣器的 PWM 波周期(这里的 ob 和 Linux 的 outb 相同) ob 0x42 (1193180/$t0)&0xff; PWM 波周期的低字节 ob 0x42 (1193180/$t0)>>8; PWM 波周期的高字节 ob 0x61 3; 开始发声 .sleep $t1; 持续发声 $t1 这么长时间(毫秒) ob 0x61 0; 发声结束
感谢 负一的平方根 (zzh1996) 出的题。