如何用汇编编写一个函数,然后用高级语言调用?如果回答详细,追加分数

speedfirst 2003-10-09 12:41:07
加精
如何用汇编编写一个函数,然后用高级语言调用?

例如用汇编语言调用BIOS功能输出“Hello,world”。然后用C语言调用此函数。
最好有详细的步骤和步骤说明。希望好心的诸位给予帮助,谢谢。
...全文
197 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
mhmx 2003-11-28
  • 打赏
  • 举报
回复
举个例子:C++Builder下实现对端口读写的两种方法

asm {

汇编语句1

……

}

利用内嵌汇编语言编制端口输出函数如下:

void OutPort(unsigned short port,unsigned char value)

//port参数为输出端口地址,value参数为输出值

{

  asm{

    mov dx , port //把端口地址送到处理器DX寄存器中

    mov al , value // 把value 送到处理器AL寄存器中

    out dx , al // 把AL寄存器中的值送到端口

};

}

该函数将无符号字符型8位的数据value写入地址为port的端口上,port的数据类型是unsigned short ,16位无符号短整形。

利用内嵌汇编语言编制端口输入函数如下:

unsigned char InPort(unsigned short port)

//port参数为输入端口地址,返回为输入值

{

  unsigned char value ;

  asm{

    mov dx , port // 把端口地址送到处理器DX寄存器中

    in al, dx // 从DX指定端口中将一数据送到AL寄存器中

    mov ind , value // 把AL寄存器中的值赋给value

    };

  return value; //返回端口数据

}

函数InPort从地址为port的端口读入一个无符号8位的字符型数据,其其参数只一个,即端口号。返回的数据为unsigned char类型的,为从端口读取的值。
ckacka 2003-10-17
  • 打赏
  • 举报
回复
这是哪儿跟哪儿啊??

________________________________________
the three great virtues of a programmer:
laziness, impatience and hubris.
--Lary Wall
zcpro 2003-10-15
  • 打赏
  • 举报
回复
内嵌,例如:
int func(int a)
{
__asm
{
mov dx,a
...
mov ax,a
}
}
maojincxj 2003-10-15
  • 打赏
  • 举报
回复
#include "CardFunctionasm.h"

//-----------------------------------------------------------------------------
void __stdcall pc7484_do(BYTE &DoData,int Port,long Delay)
{
//汇编代替读写端口
BYTE tmpByte;
BYTE *BytePtr;
BytePtr = &DoData;
int DoPort = Port + 0x0A;
for( int i=0;i<2;i++ )
{
tmpByte = BytePtr[i];
__asm
{
push EAX
push EDX
mov EDX,0
mov EDX,DoPort
mov AL,tmpByte
out DX,AL
pop EDX
pop EAX
}
DoPort++;
}

}
daizh 2003-10-15
  • 打赏
  • 举报
回复
其实,你在问问题的时候,查一下已往的帖子,你就能找到答案。实在是没有的话再提出来,这样效率高。
daizh 2003-10-15
  • 打赏
  • 举报
回复
望下面的文章对你有所帮助:


我在写定时提醒 时碰到一个问题:怎么发声?我开始是用 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 都不支持。
speedfirst 2003-10-10
  • 打赏
  • 举报
回复
内嵌俺会呀。
就是想学学如何用汇编编写一个函数,然后用高级语言调用

楼上的,让我看书也要给个书名嘛
W32API 2003-10-10
  • 打赏
  • 举报
回复
关于函数调用时参数传递规范在不同的地方有不同的定义,所以编译原理一般会有。找一本来看看
W32API 2003-10-09
  • 打赏
  • 举报
回复
参数传送的时候选取一个规范就可以了。比如 C、PASCAL、STDCALL 等
汇编在取参数的时候按照设定的规范所规定的方式取数。
C 在用 C、PASCAL、STDCALL 声明函数。
W32API 2003-10-09
  • 打赏
  • 举报
回复
写驱动。。。!!!跟这有关系?
wowocock 2003-10-09
  • 打赏
  • 举报
回复
可以参考我在黑客防线杂志10期上,<<XP内核DIY>>,里面通过结合VC,XPDDK,MASM32在驱动中加入汇编代码,在系统内部GDT,IDT上生成调用门和中断门,达到到在XP/2K/2003下的任何用户模式下执行你的任意RING0代码.
SoRoMan 2003-10-09
  • 打赏
  • 举报
回复
注意内存模式,变量定义,参数传递.基本上就OK了.
看书啊...
rabolee 2003-10-09
  • 打赏
  • 举报
回复
__asm
{
......
}
jerrymousenet2 2003-10-09
  • 打赏
  • 举报
回复
能不能给个示范程序?:)
simclock 2003-10-09
  • 打赏
  • 举报
回复
直接内嵌不行么?
speedfirst 2003-10-09
  • 打赏
  • 举报
回复
最好有源码

69,369

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧