发信人: wpf (卧龙在田), 信区: BorlandDev
标 题: delphi中使用汇编
发信站: 哈工大紫丁香 (2001年05月26日10:02:42 星期六), 站内信件
前言
----- ======
其实汇编的作用应该是在某些比较核心的功能作出自己的作用。但是在一般的程序
设计中
要涉及的不仅是核心代码,要有一个能让用户能接受的介面、容错系统、帮助系统等等
。所以
我的建议是用比较成熟地高级语言来完成这方面的工作,以减少大家不必要的精力浪费
。下面
是我把以前的别人的文章整理一下,把最主要的东东发给来,对你一定有帮助。
"汇编与其他程序接口问题分析"
----- ======
Dephi的嵌入式汇编(成都 阿杰)
Dephi中提供了几乎全部常用汇编指令的支持:MOV、JE、JMP、CMP、SHL、SHR、SAL、S
AR、POP
、PUSH、HLT....自己查吧。至于INT也能识别,不过非法操作或死机可别找我(在最早
的window95
中用Dephi3似乎可以在正确运行中断,但windows95 OEM、windows98就不对了,大概是
16位模块
的问题,还搞不清是怎么回事)
*嵌入式汇编的格式
Dephi是使用ASM...END来标志汇编语句
如:ASM
mov al,1
mov bl,al
END;
*可操作的寄存器
Dephi可用汇编管理以下寄存器:
32位寄存器EAX、EBX、ECX、EDX、ESP、EBP、ESI、EDI
16位寄存器AX、BX、CX、DX、SP、BP、SI、DI
8位寄存器AL、BL、CL、DL、AH、BH、CH、DH
16位段寄存器CS、DS、SS、ES
以及协处理器寄存器堆栈 ST
*使用汇编前的工作
教汇编的老师一再强调使用汇编要保存寄存器现场(保存使用前的寄存器状态,使用Pu
sh压栈
和Pop从栈中弹出),不过这一切对于Dephi的嵌入式汇编是没有必要的(除非你非要自
己使用
Push和Pop),因为Dephi已经帮助做了。不必担心会使数据丢掉。
*Dephi嵌入式汇编的使用方法
1。在一般函数过程中使用汇编
汇编程序段可以嵌套于其它过程中:如:
procedure TForm1.Button1Click(Sender:TObject);
var i:smallint;
begin
i=1;
asm
mov ax,i
sal ax,1
mov &i,ax
end;
showmessage(inttosrt(i));
end;
这个程序段是把16位的变量I进行左移,然后把结果用Mov &I,ax语句放入I变量所在地址
返回量。
最后显示I的值是2
2。独立的汇编程序段
汇编程序段也可以单独写成函数或过程。这就涉及到参数的传递与结果的返回。首先De
phi对于函
数的返回有一个约定:
即:整型数据:8位的使用AL返回,16位的用AX返回,32位的用EAX返回:
实型:用ST(0)返回
指针:用EAX返回
长字符串:用EAX返回其所在地址
变量:可用@Result返回
例如:一个用汇编的求和函数
function Sum(X,Y:Integer):Integer;
asm
MOV EAX,X //把32位的数放入EAX
ADD EAX,Y
MOV @Result,EAX //返回X+Y
end;
一个把字符转化为大写的函数例子
function UpCase(ch:Char):Char;
asm
CMP AL,'a'
JB @@exit
CMP AL,'z'
JA @@exit
SUB AL,'a'-'A'
@@exit:
end;
值得注意的是第二个例子中,没有象第一个那样把参数用语句放到寄存器中,这是由于
Dephi中默认
的把Byte(Char)类型放在AL中,不需要用Mov语句,但是这种函数不能是类的成员,否则
结果会出错。
3。在汇编中调用其它过程
汇编语句中的Call语句,可以用于调用其它过程,既可以是其它汇编程序段也可以是De
phi中的标准
过程:
例如:假设新建一个窗体并在上面加了一个按钮,在Click事件中写入以下代码:
procedure TForm1.Button1Click(Sender:TObject);
begin
showmessage('ok');
end;
再写一个过程-X
function TForm1.x(var i:smallint):integer;
asm
call button1Click
end;
执行X的结果就可以显示消息框。
*汇编的调试
编好了程序,没错,还好。如果有错就得用调试工具:如变量的跟踪,断点、堆栈查看
.....对于汇编还
可以用View菜单的Debug Windows的CPU窗口跟踪。
===========================
C、C++语言与汇编语言的接口设计 江苏:黄建华
-------
用C/C++和汇编语言混合编程,主要解决的是二者的接口和参数传递,参数传递包括
值传递、指针传递
、引用传递等。
下面以BorlandC3.1简单介绍一下值传递时的接口。全程用C语言编写主程序,汇编
语言编写子程序。
主程序中要声明子程序的原型,主程序CMAIN.CPP如下:
//主程序cmain.cpp
#include <stdio.h>
extern "C" int addition(int x,inty);
//此处声明子程序的原型,C必须大写,最后有分号。
void mian()
{
int x=120,y=15,z;
z=addition(x,y);
printf("x,y,z:%d,%d,%d",x,y,z);
}
BC3.1中带有用于80X86的汇编工具TASM。汇编语言中需要说明为何种语言调用、调
用的函数以及类型。
主程序调用子程序时,从后往前向堆栈中压入参数,然后是主程序的返回地址(80X86
中堆栈向低地址方向
生长)。
上面的主程序调用子程序时堆栈情况如下(Y处于高地址):
│ │↑
├─────┤
│ IP │
├─────┤
│ CS │
├─────┤
│ 参数X │
├─────┤
│参数Y │ ↓低地址
├─────┤
│ │
当从堆栈中取有关参数时要用到寄存器BP,因此还需要保存BP;
如果子程序中有自己的数据段,也要保存原有的DS。返回的结果如果是短整数,请放
在AX中;长整数请
放在DX:AX中。子程序ADDITION.ASM如下
;子程序addition.asm
.model small,c ;声明此为C/C++的子程序
.486 ;可以使用486的指令,包括387。
public addition ;addition公用,可为其它程序远调用。
.code ;代码段开始
addition proc c x:word,y:word ;addition子程序的格式
push bp ;保存BP
mov bp,sp ;把SP值传给BP
mov ax,[bp+6] ;取出X。
mov bx,[bp+8] ;取出Y。
add ax,bx ;(ax)<-x+y
pop bp ;恢复BP
ret ;返回主程序
addition endp
end
现在主程序和子程序都已经完成,下面可以用BC31来编译和连接了。
首先,进入BC主程序,选中Option/Linker/Libraries,在Libraries对话框中,选中
Turbo ision,以保证
连接时与tv.lib连接。
其次,新建或打开ADDITION.ASM,确认无误后选中=/Turbo As-sembler,汇编成功
后,选中file/dos
shell,在dos提示符下键入:
tlib tv.lib+addition.obj
如果以后addition.asm修改了,相应addition.obj也改变了,只需键入tlib tv.lib -
+ addition.obj
现在,键入exit回到BC环境。
接着,新建或打开cmain.cpp,选中Compile/Compile,对Cmain.cpp编译;选中Compil
e/Link,进行连接。
至此,一个名为cmain.exe的可执行文件产生了。
下面,再来简单看一下浮点数的调用和返回。
C/C++中,浮点数有两种:float,点四字节;doble,点八字节。浮点参数调进汇编语
言时,仍然压入堆栈,
可以用上面的方法找到参数;值返回时,只需把结果保留在80X87的TOS中即可。其余与
上相同。例程如下:
//主程序fmain.cpp
#include <stdio.h>
extern "c" double fsqr(double x);
void main()
{
double x,y ;
printf("Enter x:");
scanf("%e",&x);
y=fsqrt(x);
printf("\nx=%e\ny=%e\n,x,y);
}
;子程序fsqr.asm
.model small,c
.486
public fsqrt
.code
fsqr proc c x:dword ;X为double型,占8字节。
push bp
mov bp,sp
finit ;协处理器初始化。
fld dword prt [bp+6] ;载入X至TOS。
fsqrt; ;TOS开方,结果仍在TOS中
fwait ;与主处理器同步
pop bp
ret
fsqr endp
end (以上程序均运行通过。
--
据说呆娃儿不笨
※ 来源:·哈工大紫丁香 bbs.hit.edu.cn·[FROM: 202.118.245.166]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:6.222毫秒