2008年7月9日星期三

delphi与汇编学习3

//在Delphi圣地中发的贴子,同时也转到这里来。

呵呵,说一下关于参数的传递问题.
在C,C++等语言中函数的参数的进栈顺序是从右向左进行,比如一个函数 int Func1(int x,y),所以其入栈方式就是:
Push Y
Push X
或者
mov (esp+4),Y //由于在调用函数之前会先把调用函数之后的指令地址地址入栈保存便于程序在执行完之后能够跳到正确的地方执行,入栈之后ESP减去4个字节所以,此时的栈顶指针应该增加4个字节
mov (esp), X//然后入栈参数X
然后是Call Func1,由此可见,需要使用存储器.
关于C中的我就介绍这样多吧,呵呵,也不晓得讲的对不对,都忘记完了.

那么在Delphi中参数的传递方式又如何呢?

在Delphi中,Delphi默认的参数传递方式是通过寄存器进行传递的.其中EAX,ECX,EDX三个寄存器用来传递参数.
参数1------> EAX
参数2------> EDX
参数3------> ECX

返回类型:
Char,Byte al 寄存器
SmallInt , Word ax 寄存器
Integer,LongWord,AnsiString,Pointer,class eax 寄存器
Real48 eax 寄存器中是栈内返回值的指针
Int64 edx:eax 寄存器对
Single,Double,Extended,Comp 栈首寄存器ST(0) //呵呵,这个东西还没有搞明白

下面我们来介绍几个简单的小例子:(呵呵,高手飘过)
1.得到最大数字,一个很简单的程序
function Max(x,y: integer): integer;
asm
//前面已经说了,EAX是第一个参数,EDX是第二个参数,则可知道
//EAX中存放的就是X的值,EDX中存放的则是Y的值,现在开始:
cmp EAX,EDX //比较
Jb @Beleve //小于
ret //否则直接返回
@Beleve:
mov EAX,EDX //EAX小于EDX,所以把EDX的值放到EAX中返回
end;

2:求和
function sum(x,y: integer): integer;
asm
add eax,edx
end;

3:得到第某个数字第index位上的数字是0还是1
//这里并没有使用到Eax和Edx作为参数进行值处理,因为不好控制其分配(反正我是一下没弄清楚,呵呵,如果有兴趣的可以使用Ctrl+Alt+C打开Cpu View的Cpu调试窗口看里面的汇编代码。)
function GetBit(index: Byte;Num: integer): byte;
var
msg: string;
begin
msg := '数字位数超界!';
asm
mov cl,index
mov eax,Num
cmp cl,32 //比较是否超过32
ja @ExitMsg //超过32跳到显示消息
@cmp1:
cmp cl,1 //是否小于1
jae @ValueRet//大于等于1跳到@ValueRet

@ExitMsg:
push eax //Eax压占保存,因为后面的Showmessage需要使用Eax传递的参数
PUSH Msg //将消息MSG压栈
Pop eax //弹出参数到EAX中,呵呵其实直接 Mov eax,Msg效果一样
call showmessage //调用函数显示消息
Pop Eax //恢复Eax中的值
mov al,0
jmp @Compolete //跳到完成
@ValueRet:
sub cl,1 //计算机中真正计位从0开始,所以减1
shr eax,cl //右移Index
And eax,1 //得到该位上的值
@Compolete:
mov @result,al
end;
end;

没有评论: