发信人: 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毫秒