Windows 保護模式下,應用程式運行於 Ring 3 (用戶態),無法直接存取硬體 I/O 埠。但 PC Speaker 控制埠 (0x42/0x43/0x61) 屬於「無傷大雅」類別,Windows 未加保護,允許用戶態直接操作。本文展示如何在 C++Builder 中結合獨立組合語言模組,實現精準頻率蜂鳴器控制。
0xB6 設定通道 2、模式 3 (方波產生器)、二進位計數
extern "C" {
unsigned char InPortB(int port); // 讀取埠位元組
void OutPortB(int port, unsigned char val); // 寫入埠位元組
}
void __fastcall Sound(int freq) {
if (freq < 20 || freq > 20000) return;
int count = 1193181 / freq;
unsigned char b = InPortB(0x61);
if ((b & 3) == 0) { // 喇叭未開啟
OutPortB(0x61, b | 3); // 開啟閘門 + 喇叭
OutPortB(0x43, 0xB6); // 設定 8254 模式
}
OutPortB(0x42, (unsigned char)count); // 低位元組
OutPortB(0x42, (unsigned char)(count >> 8)); // 高位元組
}
void __fastcall NoSound() {
OutPortB(0x61, InPortB(0x61) & 0xFC); // 關閉 Bit 0/1
}
.386p
.model flat
_TEXT segment dword public use32 'CODE'
_InPortB proc near
push ebp
mov ebp, esp
mov dx, word ptr [ebp + 8] ; 參數: port
in al, dx ; 讀取埠
pop ebp
ret
_InPortB endp
_OutPortB proc near
push ebp
mov ebp, esp
mov dx, word ptr [ebp + 8] ; 參數: port
mov al, byte ptr [ebp + 12] ; 參數: value
out dx, al ; 寫入埠
pop ebp
ret
_OutPortB endp
public _InPortB
public _OutPortB
_TEXT ends
end
| 項目 | 說明 |
|---|---|
| .386p | 指示 32 位元保護模式指令集 |
| .model flat | 平坦記憶體模型 (32 位元線性位址空間) |
| 參數存取 | 32 位元呼叫慣例:參數在堆疊 [ebp+8]、[ebp+12]...,非 16 位元 [bp+6] |
| 前綴底線 | C 建構器預期 _InPortB 符號,區分大小寫 |
| public 宣告 | 匯出符號供連結器解析 |