CB和汇编混合编程

我在写定时提醒 时碰到一个问题:怎么发声?我开始是用 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 都不支持。

时间: 2024-10-26 02:05:14

CB和汇编混合编程的相关文章

关于c与汇编混合编程的一点总结

在C和汇编混合编程的时候,存在C语言和汇编语言的变量以及函数的接口问题. 在C程序中定义的变量,编译为.asm文件后,都被放进了.bss区,而且变量名的前面都带了一个下划线.在C程序中定义的函数,编译后在函数名前也带了一个下划线.例如: extern int num就会变成 .bss _num, 1 extern float nums[5]就会变成.bss _nums, 5 extern void func ( )就会变成 _func, 一 汇编和C的相互调用可以分以下几种情况: (1)汇编程序

kermit配置/反汇编/c和汇编混合编程/计算机存储介质/GPIO编程

kermit配置 反汇编 wuyingqiang@ty-kf1:~/1$ gcc hello.c  -o app wuyingqiang@ty-kf1:~/1$ gcc hello.c -g -o app -g参数决定反汇编之后的文件中,还能否看到c代码 wuyingqiang@ty-kf1:~/1$ objdump -dSsx app > file 两种情况下, cat file. 查看文件内容,c代码出会不一样. wuyingqiang@ty-kf1:~/1$ file app  app:

C和C++混合编程问题_C 语言

分析以下一段代码: /*=======sum.h=========*/ #ifndef SUM_H #define SUM_H #include <stdio.h> int sum(int a,int b); #endif; /*=======sum.c=========*/ #include "sum.h" int sum(int a,int b) { int c=a+b; return c; } /*====main.cpp======*/ #include "

c/c++/asm 混合编程

c/c++/asm 混合编程        C语言不支持函数重载,编译不通过,其出错信息为:[Error] :conflicting types for '函数名'. C++调用C: 一般extern 语句作用: 对于规模较大的程序,往往分成多个模块进行编写.对所有模块共同使用的全局变量和函数,如果在所有的模块中都定义,连接时将会出错. 解决方案:只在一个模块中定义(如int x;),在其他模块中用extern语句声明(extern int x;)这是一个外来的变量. extern语句还可用于前

C++与Java混合编程

本文配套源码 现在的程序员,不再像以前一样,掌握一种编程语言就可以混得有模有样了,现实的情况是,真实的项目中,通常是涉及多种编程语言,举几个简单的例子,一个软件为了快速开发,可能是使用Delphi或VB作为界面开发首选语言,底层的指令或核心算法,会使用C/C++处理,涉及数据处理的时候,为了安全和快速开发,会使用Javascript或Python等脚本语言实现数据分析处理.因此,开发者应该学习或掌握语言混合编程. C++和Java是主流的两种编程语言,但是现在整个网上对实现这两种语言混合编程的资

C++ Builder与Matlab混合编程的实现

在C++Builder中调用Matlab工具箱函数,有两种实现方式.一种是基于Matlab环境支持,通过必要的设置实现:笔者在本刊上曾撰文对这种方式进行了专门的阐述.另一种则是完全脱离Matlab环境,通过动态连接库方式实现对Matlab工具箱函数的调用,这可以通过一种开发平台Mediva来实现.相对来说,前者的限制因素较多,而后者则较为方便灵活. 一.Mediva软件平台 Mediva是Mathtools公司推出的一种Matlab编译开发软件平台,提供对Matlab程序文件(M文件)的解释执行

VC++与MATLAB混合编程及其应用

摘 要 本文详述了在VC++6.0编译环境下如何利用Matlab来实现应用系统的设计和分析, 介绍了通过Matlab与VC应用程序连接的常用方法,分析了VC与Matlab的混合编程的步骤,最 后通过一个具体实例的实现过程对上述方法进行了应用性介绍. 关键词 VC++: Matlab:混合编程 Matlab 是由Math Works 公司于1984 年推出的数值计算及图形处 理软件,可以实现数值分析.优化.统计.偏微分方程数值解.自动控制.信号处理.图像 处理等若干领域的计算和图形显示功能.其中,

VB与VC混合编程中处理消息的方法

现在越来越多的人采用VB与VC的混合编程:用VB快速开发出漂亮的界面以及外围处理程序,再用VC编写底层的各种操作,例如内存的操作.IO端口的操作等,VC中还可以嵌入汇编语言进行更底层的操作. 一般的做法是将VC程序编译成DLL,在VB中用Declare语句声明DLL中的函数,例如: Declare Function SendCommand Lib ″c:\program files\devstudio\wjfprojects\Hr0506dllMnsr\debug\Hr0506dllMnsr.d

托管C++中GDI+和GDI混合编程技术

1.引言 早期的Windows程序中,可以使用GDI(Graphics Device Interface,图形设备接口)在一个窗体中绘制图形.文本和图像,但它的功能比较有限,尤其是图像处理方面.GDI+是GDI的一个新版本,它不仅在GDI基础上添加许多新特性,而且对原有的GDI功能进行优化,并在为开发人员提供的二维矢量图形.文本.图像处理.区域.路径以及图形数据矩阵等方面构造了一系列相关的类.其中,图形类Graphics是GDI+接口中的一个核心类,许多绘图操作都可用它来完成. 与GDI相比,G