<b>CB和汇编混合编程</b>[VC/C++编程]
本文“<b>CB和汇编混合编程</b>[VC/C++编程]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:
我在写按时提醒 时碰到一个问题:怎么发声?我开始是用 32 位 Windows 的 API 函数 MessageBeep( -1 ); 那声音又小又刺耳.本来在 16 位的 Windows API 中有的一套 PlaySound 的函数在 32 位 Windows 中又撤消了, DOS 下的 Sound 函数更是早就不能用了.
好在我对硬件还算理解,知道 PC Speaker 的声音是通过系统中的按时计数芯片 8253/8254 产生的,只要通过硬件端口拜候芯片便可以产生想要的声音了. 问题在于 Windows 是工作在保护情势下,大大都硬件端口都要在特权级0(PL0, 这是搞硬件的人的说法,后来我才知道在搞 OS 和 Driver 的人中是叫 Ring 0 的, 这才对比精确,因为假如不是 Intel 的 CPU 大概就不叫 PL 了)中, 即操作系统核心态中,才可以拜候(比方硬盘口,拜候时是不会出错,但后果不精确), 这也就意味着要写成驱动程序的情势,天啊! VxD 和 WDM 我都不会,怎么办? 事实上没有这么艰难,像 PC Speaker 这种无伤大体的端口, Windows 是不保护的, 即在用户态下也可以正常拜候.
目前还有一个问题就是用什么语句拜候端口? DOS 中 C 语言里的那几个端口操作函数在 Windows 中都撤消了,只好用汇编.我开始是用 ASM 语句插入汇编代码,后果发现 BCB 在编译时碰到 ASM 时会把 BCB 文件编译成一个宏大的 ASM 文件, 再重新启动汇编程序汇编,速度太慢.最后采取了我在 DOS 编程经常用的办法, 做一个单独的 ASM 文件加入工程文件中.
下面是两个用于发声的函数,最前面声明了两个外部 C 调用情势的函数, 是两个用汇编写的字节端口输入/输出函数,注意:在 C++ 中一定要注不测部函数应为 C 调用情势.程序中多处强迫范例转换是为了不呈现告诫,我对程序一向要求 Error/Warning/Hint 全为 0.
extern "C" {
Byte InPortB( int aPort );
void OutPortB( int aPort, Byte aValue );
}
void __fastcall Sound( int aFreq )
{
if ( ( aFreq >= 20 ) && ( aFreq <= 20000 ) )
{
aFreq = 1193181 / aFreq;
Byte b = InPortB( 0x61 );
if ( ( b & 3 ) == 0 )
{
OutPortB( 0x61, Byte( b | 3 ) );
OutPortB( 0x43, 0xb6 );
}
OutPortB( 0x42, ( Byte )aFreq );
OutPortB( 0x42, ( Byte )( aFreq >> 8 ) );
}
}
void __fastcall NoSound( void )
{
Byte b = Byte( InPortB( 0x61 ) & 0xfc );
OutPortB( 0x61, b );
}
下面是两个端口 I/O 的函数的汇编源程序,即按时提醒(Alarm)中的 IOPortB.asm 文件的全部内容,是在 BCB 产生的 ASM 文件底子上作了一点点的优化. 注意:
1 、最前面的 .386p 必不可少,指定用 32 位保护情势,至于 modal flat 我也不太懂得是 What ,跟 16 位时的 tiny, small... 差别,大约是指用 32 位保护情势的平展地址间情势吧;
2 、在 32 位保护情势中, CS/IP 为 32 位,参数在栈中的位置与 16 位时差别;
3 、最后的 public 也不可少,前缀的下划线也是必须的,别的记得用大小写敏感方法汇编.
.386p
model flat
_TEXT segment dword public use32 ''CODE''
_InPortB proc near
push ebp
mov ebp, esp
mov dx, word ptr [ebp + 8]
in al, dx
pop ebp
ret
_InPortB endp
_OutPortB proc near
push ebp
mov ebp, esp
mov dx, word ptr [ebp + 8]
mov al, byte ptr [ebp + 12]
out dx, al
pop ebp
ret
_OutPortB endp
public _InPortB
public _OutPortB
_TEXT ends
end
注意:此法在 Windows NT 上行不通,因为 Windows NT 保护了全部的端口,必须用 WDM,连 VxD 也不行,它只用于 Windows 95 ,在 Windows 98 中也可以用,但 Windows NT 和 Windows 2000 都不支持.
以上是“<b>CB和汇编混合编程</b>[VC/C++编程]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:
本文地址: | 与您的QQ/BBS好友分享! |