主题:调用约定演示例子
主持:A3.武稀松
时间:2005-02-01 15:00
2005-02-01 14:50:02 A3.武稀松(42088303)
本来想找一点时间给大家讲一下组件设计,BASM等.时间不太够.所以今天下午抽出一小段时间说一下调用约定
2005-02-01 14:51:26 A3.武稀松(42088303)
大家都知道Delphi最常用得函数调用约定方式吧
2005-02-01 14:51:27 乾隆(7891551)
谁再安排下讲点最简单的东西吧,比如类好吗
2005-02-01 14:52:07 D8 。飘尘(43745429)
从左还是从右传值对吧
2005-02-01 14:52:23 A3.武稀松(42088303)
很多书上都有,什么从左到右传参数,从右到左传参数得.我就给大家一些形象具体的例子开始讲起
2005-02-01 14:52:55 B4.松鼠(64652023)
A3在会议室开课哦
2005-02-01 14:53:03 A3.武稀松(42088303)
D8你说Delphi最常见的几种调用约定都有什么呢
2005-02-01 14:53:17 乾隆(7891551)
好,什么是从左到右,什么是从右到左?
2005-02-01 14:53:35 D8 。飘尘(43745429)
有4种吧,偶不记得了
2005-02-01 14:53:43 A1.笑熬糨糊(2282902)
我们可以从最简单的方式讲起。
2005-02-01 14:53:50 D8.飘尘(43745429)
STDCALL偶记得了
2005-02-01 14:53:52 A1.笑熬糨糊(2282902)
就是Delphi默认的方式。
2005-02-01 14:54:13 A3.武稀松(42088303)
第一种Delphi默认的调用方是Register寄存器方式
2005-02-01 14:54:26 D8 。飘尘(43745429)
Register对对
2005-02-01 14:54:42 A3.武稀松(42088303)
procedure A(Param1,Param2:String);register;
begin
ShowMessage(Param1+Param2);
end;
2005-02-01 14:55:32 A3.武稀松(42088303)
register关键字就是表示寄存器传参数方式,如果没有说明的话,编译器默认就编译成这种形式
2005-02-01 14:56:04 A1.笑熬糨糊(2282902)
Right,正解!
2005-02-01 14:56:07 A3.武稀松(42088303)
这种调用传递参数的方式是这样:
从左到右,优先使用寄存器(EAX,EDX,ECX),然后使用栈(也就是剩下的参数采用Pascal方式调用)
Delphi默认调用方式,是运行效率最高的调用方式.
2005-02-01 14:57:02 A3.武稀松(42088303)
形象一点给大家用汇编写一下调用的例子就明白了
2005-02-01 14:57:18 A1.笑熬糨糊(2282902)
就上午的例子也可以了。
2005-02-01 14:57:29 A3.武稀松(42088303)
procedure TForm1.Button1Click(Sender: TObject);
var
lA,lB:String;
begin
lA:='A';
lB:='B';
A('A','B');
end;
2005-02-01 14:58:04 A3.武稀松(42088303)
调用我上面说的函数,实际上和这样的调用等价
2005-02-01 14:58:11 A3.武稀松(42088303)
procedure TForm1.Button1Click(Sender: TObject);
var
lA,lB:String;
begin
lA:='A';
lB:='B';
//A('A','B');
asm
push EAX //把EAX压入栈中,就是保存起来
mov EAX, lA //把lA付给第一个参数
mov EDX, lB //把lB付给第二个参数
call A //调用A
pop EAX //把EAX从栈中弹出,回复EAX
end;
end;
2005-02-01 14:59:38 A3.武稀松(42088303)
mov EAX, lA //把lA付给第一个参数
mov EDX, lB //把lB付给第二个参数
这两行就是把参数放进寄存器中
2005-02-01 14:59:50 A1.笑熬糨糊(2282902)
Right,正解!
2005-02-01 15:00:12 A3.武稀松(42088303)
这个可能是比较常用的调用方式中效率最高的了
2005-02-01 15:00:33 A3.武稀松(42088303)
//有人谁说VC的__fastcall方式效率也差不多
__fastcall从右到左,优先使用寄存器(ECX,EDX),然后使用栈.关键是EAX寄存器的速度最快
所以还是Delphi的Regiser方式效率要搞一点,而且多了一个用寄存器传递的参数在参数大于
2个的时候效率更加明显,因为栈比寄存器要慢
2005-02-01 15:00:46 乾隆(7891551)
//A('A','B');这句啥意思
2005-02-01 15:01:13 A3.武稀松(42088303)
我注释掉的.和我下面的汇编代码等价
2005-02-01 15:01:14 兰铃子(105351942)
A,B连接
2005-02-01 15:01:27 A3.武稀松(42088303)
procedure A(Param1,Param2:String);register;
begin
ShowMessage(Param1+Param2);
end;
2005-02-01 15:01:34 A3.武稀松(42088303)
调用函数A
2005-02-01 15:01:43 乾隆(7891551)
连成个新的字符'AB'给变量A吗
2005-02-01 15:01:49 D10.天地弦(185511468)
所以参数2个最适合?
2005-02-01 15:02:06 B6.银狼(43225570)
武大写的例子么?给我一个被
2005-02-01 15:02:08 A3.武稀松(42088303)
不一定两个最合适
2005-02-01 15:02:22 D8 。飘尘(43745429)
什么事呀
2005-02-01 15:02:25 A3.武稀松(42088303)
我的例子是一边说一边写的
2005-02-01 15:02:37 B6.银狼(43225570)
哦
2005-02-01 15:02:35 太/rose阳(5704127)
3哥,真棒!
2005-02-01 15:02:52 D3.天之痕若虹(86278566)
晕,睡过头了
2005-02-01 15:02:59 A3.武稀松(42088303)
我们在来说一下第二种调用方式 Pascal方式
2005-02-01 15:03:21 A1.笑熬糨糊(2282902)
参数三个之内比较适合。
2005-02-01 15:04:03 D10.天地弦(185511468)
也就是这个原因?
2005-02-01 15:04:04 A3.武稀松(42088303)
A1说得对,三个以内效率最高.大于三个,后面的参数效率和Pascal方式相同
2005-02-01 15:04:51 A3.武稀松(42088303)
Pascal方式参数传递从左到右,通过栈传递
这个是Win31时代API的标准调用方式,讽刺意味的是当时看不起Pascal的C程序员也不得不这样调用
2005-02-01 15:04:59 A3.武稀松(42088303)
我们把刚才的函数修改一下
2005-02-01 15:05:07 A3.武稀松(42088303)
procedure B(Param1,Param2:String);Pascal;
begin
ShowMessage(Param1+Param2);
end;
2005-02-01 15:05:19 A3.武稀松(42088303)
这样的形式就是Pascal方式调用
2005-02-01 15:05:31 乾隆(7891551)
哦,长知识了,呵呵
2005-02-01 15:06:19 D10.天地弦(185511468)
pascal是从左到右?
2005-02-01 15:06:29 D10.天地弦(185511468)
stdcall, safecall是从右到左
2005-02-01 15:06:42 D10.天地弦(185511468)
register是从左到右
2005-02-01 15:07:04 A3.武稀松(42088303)
D10我说的Pascal方式还没说道那两种方式呢
2005-02-01 15:07:05 A3.武稀松(42088303)
procedure TForm1.Button2Click(Sender: TObject);
var
lA,lB:String;
begin
lA:='A';
lB:='B';
//B('A','B');
asm
push la //把la压入栈
push lb //把lb压入栈
call B
end;
end;
2005-02-01 15:07:54 A3.武稀松(42088303)
D10看我把la和lb压入栈得顺序,你说参数的顺序是先左还是还是先右呢
2005-02-01 15:08:03 D10.天地弦(185511468)
==
2005-02-01 15:08:09 D10.天地弦(185511468)
lb,la
2005-02-01 15:08:15 A3.武稀松(42088303)
好,大家可以执行一下我上面的代码
2005-02-01 15:08:34 D10.天地弦(185511468)
pop时先出来lb,再la
2005-02-01 15:08:39 A3.武稀松(42088303)
我也趁机写下两种调用方式的例子
2005-02-01 15:08:46 乾隆(7891551)
LA,LB是什么,我只听过AX,BX,CX,DX,什么时候来了个LA,LB啊
2005-02-01 15:09:06 A1.笑熬糨糊(2282902)
变量。
2005-02-01 15:09:06 D10.天地弦(185511468)
变量
2005-02-01 15:09:09 A3.武稀松(42088303)
乾隆,那两个是普通变量!!!
2005-02-01 15:09:22 D10.天地弦(185511468)
不看申明
2005-02-01 15:09:26 乾隆(7891551)
啊[:L]我以为是很 高深的东西呢
2005-02-01 15:09:27 A3.武稀松(42088303)
可能是我的名字起的不好
2005-02-01 15:09:44 A1.笑熬糨糊(2282902)
还好不是起个AX是BX
2005-02-01 15:10:10 A3.武稀松(42088303)
要是AL,BL也不行啊
2005-02-01 15:10:44 D10.天地弦(185511468)
3哥,你这个Demo有没有共享?
2005-02-01 15:10:45 A3.武稀松(42088303)
这个调用方是还有什么疑问么,我要往下说了
2005-02-01 15:11:00 乾隆(7891551)
对,我的表达能力非常好,等我成高手了,讲课没有人听不懂的,我能把猪都教会编程,嘿嘿
2005-02-01 15:11:04 A3.武稀松(42088303)
我一边讲,一边写.现在没有现成的DEMO
2005-02-01 15:11:15 A1.笑熬糨糊(2282902)
[coffee]
2005-02-01 15:11:24 D10.天地弦(185511468)
[;P]
2005-02-01 15:11:50 D8 。飘尘(43745429)
pop时先出来lb,再la 错了吧
2005-02-01 15:11:57 D8 。飘尘(43745429)
是先LA 再LB吧
2005-02-01 15:12:16 D10.天地弦(185511468)
谁说
2005-02-01 15:12:22 乾隆(7891551)
后压的先出来
2005-02-01 15:12:28 D10.天地弦(185511468)
嗯
2005-02-01 15:12:29 A3.武稀松(42088303)
不用Pop
2005-02-01 15:12:33 D8 。飘尘(43745429)
看错了。我以为先进LA了
2005-02-01 15:12:57 A3.武稀松(42088303)
因为参数的恢复是被调用方负责的
----------------------运行没反应的原因
2005-02-01 15:23:24 A1.笑熬糨糊(2282902)
是QQ的原因,因为,QQ复制是,只COPY了#13,没有COPY#10,所以Delphi编译出错
----------------------
2005-02-01 15:25:33 A3.武稀松(42088303)
既然解决了,我们就接着说下一个stdcall方式调用
2005-02-01 15:26:03 A3.武稀松(42088303)
从右到左,通过堆栈传递
VB默认就是这个调用方式,Win32的API也是采用这种声明方式
2005-02-01 15:26:23 D10.天地弦(185511468)
从右到左
2005-02-01 15:26:25 D10.天地弦(185511468)
对
2005-02-01 15:26:36 D10.天地弦(185511468)
是说stdcall,safecall?
2005-02-01 15:26:42 A3.武稀松(42088303)
procedure C(Param1,Param2:String);stdcall; //SafeCall编译器特殊处理等同Stdcall
begin
ShowMessage(Param1+Param2);
end;
2005-02-01 15:26:50 兰铃子(105351942)
我也OK了。
2005-02-01 15:27:59 A3.武稀松(42088303)
procedure TForm1.Button3Click(Sender: TObject);
var
lA,lB:String;
begin
lA:='A';
lB:='B';
//B('A','B');
asm
push lb
push la
call C
end;
end;
D10看看参数的传递次序
2005-02-01 15:28:24 A3.武稀松(42088303)
你看先把哪个一个参数压入栈里面的
2005-02-01 15:28:25 兰铃子(105351942)
BA
2005-02-01 15:28:34 D10.天地弦(185511468)
是从右到左
2005-02-01 15:28:55 A3.武稀松(42088303)
兰铃子的反了
2005-02-01 15:28:58 A3.武稀松(42088303)
是AB
2005-02-01 15:29:02 兰铃子(105351942)
恩
2005-02-01 15:29:11 兰铃子(105351942)
我没把LB,LA,换了
2005-02-01 15:29:19 兰铃子(105351942)
道理一样啦。呵呵
2005-02-01 15:29:36 A3.武稀松(42088303)
现在的API的调用约定都是这样的
2005-02-01 15:29:36 D10.天地弦(185511468)
[:L]
2005-02-01 15:30:28 D10.天地弦(185511468)
==
2005-02-01 15:30:31 D10.天地弦(185511468)
3哥
2005-02-01 15:30:34 A3.武稀松(42088303)
我们写DLL的时候通常也采用这样的调用方式,主要是为了和其他的语言兼容.如果紧紧在Delphi中使用我建议使用寄存器方式调用
2005-02-01 15:30:36 兰铃子(105351942)
长知识了。
2005-02-01 15:30:47 A3.武稀松(42088303)
D10要说什么
2005-02-01 15:31:02 D10.天地弦(185511468)
asm
push la; //把la压入栈
push lb; //把lb压入栈
call b;
end;
一样的
b(la,lb)
2005-02-01 15:31:06 D10.天地弦(185511468)
是吧
2005-02-01 15:31:15 A3.武稀松(42088303)
什么意思
2005-02-01 15:31:26 A3.武稀松(42088303)
对呀,就是次序不对而已
2005-02-01 15:32:01 兰铃子(105351942)
B是什么方式的啊 ?
2005-02-01 15:32:10 A3.武稀松(42088303)
B是Pascal方式的
2005-02-01 15:32:18 兰铃子(105351942)
哦
2005-02-01 15:32:40 A3.武稀松(42088303)
我们代码写的简单,编译器好辛苦啊.他要按照函数的声明不同,编译出不一样的代码
2005-02-01 15:33:07 A3.武稀松(42088303)
这个调用约定没问题了吧
2005-02-01 15:33:16 兰铃子(105351942)
如果B是stdcall方式的呢?
2005-02-01 15:33:27 A3.武稀松(42088303)
C不就是么
2005-02-01 15:33:46 A3.武稀松(42088303)
我要继续讲下一个调用约定了
2005-02-01 15:34:00 兰铃子(105351942)
procedure TForm1.Button2Click(Sender: TObject);
var
la,lb:string;
begin
la:='a';
lb:='b';
c(la,lb);
2005-02-01 15:34:08 A3.武稀松(42088303)
cdecl方式的调用
2005-02-01 15:34:17 兰铃子(105351942)
运行结果是什么啊?
2005-02-01 15:34:49 A3.武稀松(42088303)
等下再说.我先继续
2005-02-01 15:35:09 A3.武稀松(42088303)
cdecl参数是从右到左,通过堆栈传递(与C\C++默认调用约定兼容)比较原始,需要约定需要调用者来清除堆栈
2005-02-01 15:35:49 A3.武稀松(42088303)
大家看cdecl和stdcall的约定有什么区别?
2005-02-01 15:35:58 A3.武稀松(42088303)
D10你来说说
2005-02-01 15:37:02 A3.武稀松(42088303)
D10是不是溜了
2005-02-01 15:38:28 A1.笑熬糨糊(2282902)
我在试中。。。
2005-02-01 15:38:35 D10.天地弦(185511468)
晕啊
2005-02-01 15:38:42 D10.天地弦(185511468)
我的机又死了一次
2005-02-01 15:39:33 A3.武稀松(42088303)
cdecl和stdcall的区别就在于要调用者手工恢复参数栈,所以说是比较原始的一种方式
2005-02-01 15:39:53 D10.天地弦(185511468)
现在是不是不用了
2005-02-01 15:39:58 D10.天地弦(185511468)
cdecl
2005-02-01 15:40:06 A3.武稀松(42088303)
procedure D(Param1,Param2:String);cdecl ;
begin
ShowMessage(Param1+Param2);
end;
2005-02-01 15:40:43
D6.岚(151951212)
cdecl这种方式现在已经很少使用了,一般都是用stdcall了
2005-02-01 15:40:56 A3.武稀松(42088303)
调用方式和stdcall很类似,不过要手工恢复栈才行
2005-02-01 15:41:05 D10.天地弦(185511468)
哦
2005-02-01 15:41:19 D10.天地弦(185511468)
我在InsideVCL上都没有介绍这种方式了
2005-02-01 15:41:17 A3.武稀松(42088303)
procedure D(Param1,Param2:String);cdecl ;
begin
ShowMessage(Param1+Param2);
end;
2005-02-01 15:41:29 A3.武稀松(42088303)
procedure TForm1.Button4Click(Sender: TObject);
var
lA,lB:String;
begin
lA:='A';
lB:='B';
asm
push lb
push la
call D
pop la //调用方要自己恢复栈
pop lb //调用方要自己恢复栈
end;
end;
2005-02-01 15:41:43 A3.武稀松(42088303)
依然还是可以调用的
2005-02-01 15:42:26 兰铃子(105351942)
怪不得刚才出那样的错了。
2005-02-01 15:42:33 A3.武稀松(42088303)
这种调用方式还是有用的
2005-02-01 15:42:54
D6.岚(151951212)
有什么用?相对而言,不是stdcall会方便一些吗?
2005-02-01 15:42:59 B2.TCP INFO(31329846)
cdecl
2005-02-01 15:43:08
D6.岚(151951212)
cdecl不是早期的东西了吗?
2005-02-01 15:43:14 A3.武稀松(42088303)
C/C++里面依然还在广泛使用.特别是C/C++的主函数必须是cdecl方式的,不能改的
2005-02-01 15:43:28 A3.武稀松(42088303)
C/C++里面依然还在广泛使用.特别是C/C++的主函数必须是cdecl方式的,不能改的
2005-02-01 15:43:33 B2.TCP INFO(31329846)
由右至左
2005-02-01 15:43:56 D8 。飘尘(43745429)
哈哈以前看过差不多忘记了,还在学校读书时
2005-02-01 15:44:03 A3.武稀松(42088303)
有一些时候例如C里面的Printf函数谁用过?
2005-02-01 15:44:16 兰铃子(105351942)
我用过
2005-02-01 15:44:17 D10.天地弦(185511468)
3哥,如果cdecl不用汇编怎么pop出来
2005-02-01 15:44:18 B2.TCP INFO(31329846)
我这有书,哪里不明,我可以打上来
2005-02-01 15:44:25 D8 。飘尘(43745429)
PRINTF偶当然用过了
2005-02-01 15:44:36 A3.武稀松(42088303)
他的参数数目是不固定的,所以由调用者一方回复会比较方便实现
2005-02-01 15:44:41 D3.天之痕若虹(86278566)
现在可以调用那函数吗?
asm里的
2005-02-01 15:45:12 A3.武稀松(42088303)
D10.天地弦(185511468) 15:44:17
3哥,如果cdecl不用汇编怎么pop出来
----------------------
编译器在编译的时候会处理的,调用完会自动回复参数的
2005-02-01 15:45:25 乾隆(7891551)
asm
push lb
push la
call D //为什么调用前汇编语言一定呀压入呢,汇编怎么知道要这么做,还知道起调用DELPHI定义的函数,不理解啊
2005-02-01 15:46:05 A3.武稀松(42088303)
乾隆,这是编译器为你做好的.我用汇编写只是让你更清楚编译器都为我们做了什么
2005-02-01 15:46:11 D10.天地弦(185511468)
call 就是调用过程了
2005-02-01 15:46:34 A3.武稀松(42088303)
这四大类我都讲完了.还有一个要提一下
2005-02-01 15:46:56 A1.笑熬糨糊(2282902)
什么东西要提?
2005-02-01 15:46:59 A3.武稀松(42088303)
就是A1上午说的成员函数的问题
2005-02-01 15:47:30 A1.笑熬糨糊(2282902)
就是Self的问题?
2005-02-01 15:47:35 乾隆(7891551)
我在想CALL D 若这个D过程也是在ASM 里用汇编语言写的就可以理解了,用DELPHI前面定义的,汇编竟然也知道怎么调用,奇怪
2005-02-01 15:47:42 兰铃子(105351942)
我要听SELF。
2005-02-01 15:47:46 A3.武稀松(42088303)
成员函数其实也是可以加上这些调用约定的.不加的话默认是寄存器传递参数的方式
2005-02-01 15:48:10 D10.天地弦(185511468)
[v]
2005-02-01 15:48:10
D6.岚(151951212)
在Delphi中,寄存器方式是最快的
2005-02-01 15:48:19 A1.笑熬糨糊(2282902)
如果是调用普通函通,EAX是第一个参数,如果是调用成员函数,EAX是Self.
2005-02-01 15:48:21 D10.天地弦(185511468)
[图片]
2005-02-01 15:48:23 D10.天地弦(185511468)
下面是谁
2005-02-01 15:48:28 D10.天地弦(185511468)
咱没有名
2005-02-01 15:48:27 大羽(393921295)
寄存器有限
2005-02-01 15:48:44 乾隆(7891551)
你讲这几种调用方式结论是想告诉什么,是D10总结的这句吗,若是我记住这句话就可以了,呵呵
2005-02-01 15:48:44 大羽(393921295)
有32个?
2005-02-01 15:48:46 D10.天地弦(185511468)
嗯,
2005-02-01 15:48:47 A3.武稀松(42088303)
但是成员函数有一个特殊的地方,编译器会为它加一个参数Self,而且Self永远都是第一个参数
2005-02-01 15:49:00 A3.武稀松(42088303)
所以
2005-02-01 15:49:50 A3.武稀松(42088303)
A1默认状态下成员函数是寄存器方式,而Self又是第一个参数,所以EAX就是那个Self了
2005-02-01 15:50:02 A1.笑熬糨糊(2282902)
Right,正解!
2005-02-01 15:50:03 A3.武稀松(42088303)
默认状态下成员函数是寄存器方式,而Self又是第一个参数,所以EAX就是那个Self了
2005-02-01 15:50:27 乾隆(7891551)
EAX和以前的AX寄存器有什么区别啊
2005-02-01 15:50:30 A3.武稀松(42088303)
procedure E(Param1,Param2:String);
.....
procedure TForm1.E(Param1,Param2:String);
begin
ShowMessage(Param1+Param2 + Self.Caption);
end;
2005-02-01 15:50:39 D10.天地弦(185511468)
A1.笑熬糨糊(2282902) 15:48:19
如果是调用普通函通,EAX是第一个参数,如果是调用成员函数,EAX是Self.
---------
普能函数EAX也是第一个参数,只是第一个参数为Self
2005-02-01 15:51:06 A3.武稀松(42088303)
EAX是32位寄存器,AX是16位的,EAX的低16位就是旧的AX
2005-02-01 15:51:22 乾隆(7891551)
这样的啊
2005-02-01 15:51:28 A3.武稀松(42088303)
procedure TForm1.Button5Click(Sender: TObject);
var
lA,lB:String;
begin
lA:='A';
lB:='B';
{
//E(lA,lB);
asm
mov EDX,la
mov ECX,lb
//实际上因为是在TForm1.Button5Click方法里面执行,所以EAX现在就是Self,可以省略
call TForm1.E
end;}
//Form1.E(lA,lB);
asm
mov EDX,la
mov ECX,lb
mov EAX,Form1
call TForm1.E
end;
end;
2005-02-01 15:51:29 A1.笑熬糨糊(2282902)
普能函数EAX也是第一个参数,只是第一个参数为Self <-?
2005-02-01 15:51:38 B1.斜阳(249208513)
还有一个不太显著的差别,就是Delphi在对类方法的调用和对普通方法的调用不太一样
2005-02-01 15:52:12 A1.笑熬糨糊(2282902)
B1出来踢局了。[:D]
2005-02-01 15:52:22 A3.武稀松(42088303)
上面的汇编代码就是对成员函数的调用
2005-02-01 15:52:40 B1.斜阳(249208513)
[:X]
2005-02-01 15:53:49 D10.天地弦(185511468)
[:L]
2005-02-01 15:53:50 B1.斜阳(249208513)
Delphi在对类方法和对类中普通方法虽然第一个参数都是self,但是,两个self却不一样,这就是区别了
2005-02-01 15:54:16 A1.笑熬糨糊(2282902)
Right,正解!
2005-02-01 15:54:23 乾隆(7891551)
怎么QQ不动了
2005-02-01 15:54:43 B1.斜阳(249208513)
对类方法的调用,其中的self是指向类本身的,对类中普通方法的调用,self是指向类的实例的
2005-02-01 15:54:55 A3.武稀松(42088303)
类方法中的Self指类,普通成员函数的Self指当前实例
2005-02-01 15:55:21 D10.天地弦(185511468)
en
2005-02-01 15:55:36 A3.武稀松(42088303)
我说的EAX中的仅仅是Self.当它是类方法的时候就是类,否则是当前实例
2005-02-01 15:56:09 D10.天地弦(185511468)
明
2005-02-01 15:56:35 A3.武稀松(42088303)
编译器会在方法所有参数前插入self参数.其实还是普通的寄存器调用方是
2005-02-01 15:56:35 乾隆(7891551)
半明半不明
2005-02-01 15:57:02 D10.天地弦(185511468)
编译器会在方法所有参数前插入self参数.其实还是普通的寄存器调用方式
2005-02-01 15:57:14 A3.武稀松(42088303)
我把代码打包一下,传到共享里
2005-02-01 15:57:56 D10.天地弦(185511468)
D10.天地弦(185511468) 15:53:07
A1.笑熬糨糊(2282902) 15:48:19
如果是调用普通函通,EAX是第一个参数,如果是调用成员函数,EAX是Self.
---------
普能函数EAX也是第一个参数,只是成员函数第一个参数为Self--->开始漏了几个字成员函数
2005-02-01 15:58:12 D10.天地弦(185511468)
A3.武稀松(42088303) 15:56:35
编译器会在方法所有参数前插入self参数.其实还是普通的寄存器调用方,是 .....
2005-02-01 15:58:24 D10.天地弦(185511468)
我开始这样读的
2005-02-01 15:58:23 ygm(81379503)
你们讨论好激烈阿
2005-02-01 15:58:33 ygm(81379503)
很好玩啊
2005-02-01 15:58:47 A1.笑熬糨糊(2282902)
技术讨论需要激烈
2005-02-01 15:58:48 A3.武稀松(42088303)
已经传到群共享里面了
2005-02-01 15:58:55 ygm(81379503)
可惜我正在赶项目
2005-02-01 15:59:27 ygm(81379503)
聊天记录,以后能看到吗?
2005-02-01 15:59:52 A3.武稀松(42088303)
有一个有趣的现象D10想想为什么会这样
2005-02-01 15:59:59 布袋猫(6148012)
[:D]真的是字符在作怪呢,俺成功了
2005-02-01 16:00:06 A3.武稀松(42088303)
procedure TForm1.Button1Click(Sender: TObject);
var
B:TButton;
begin
ShowMessage(B.Caption);
end;
2005-02-01 16:00:06 D10.天地弦(185511468)
我看看
2005-02-01 16:00:25 A3.武稀松(42088303)
和今天说的有一点关系
2005-02-01 16:00:24 D10.天地弦(185511468)
这个?
2005-02-01 16:00:52 A3.武稀松(42088303)
你看看运行结果是什么
2005-02-01 16:00:57 B6.银狼(43225570)
不会错误的?
2005-02-01 16:01:11 B6.银狼(43225570)
是 button1么
2005-02-01 16:01:11 D10.天地弦(185511468)
是Button1
2005-02-01 16:01:20 D10.天地弦(185511468)
奇怪
2005-02-01 16:02:07 B6.银狼(43225570)
奇怪什么?
2005-02-01 16:02:38 D10.天地弦(185511468)
为什么是"Button1"
2005-02-01 16:03:19 B6.银狼(43225570)
上午不是说了
2005-02-01 16:03:51 D10.天地弦(185511468)
老大那个例子
2005-02-01 16:04:02 B6.银狼(43225570)
对
2005-02-01 16:04:41 D10.天地弦(185511468)
procedure TForm1.Button6Click(Sender: TObject);
var
B: TButton;
begin
showmessage(B.Caption);
end;
2005-02-01 16:04:51 D10.天地弦(185511468)
我这里显示是Button6
2005-02-01 16:05:34 D10.天地弦(185511468)
procedure TForm1.FormClick(Sender: TObject);
var
B: TButton;
begin
showmessage(B.Caption);
end;
2005-02-01 16:05:38 D10.天地弦(185511468)
是显示Form1
2005-02-01 16:06:05 A3.武稀松(42088303)
呵呵
2005-02-01 16:06:11 A3.武稀松(42088303)
嘿嘿嘿
2005-02-01 16:06:33 B6.银狼(43225570)
[图片]
2005-02-01 16:06:37 B6.银狼(43225570)
我的是这样的
2005-02-01 16:06:41 D10.天地弦(185511468)
3哥,你说说
2005-02-01 16:07:00 D10.天地弦(185511468)
[图片]
2005-02-01 16:07:08 A3.武稀松(42088303)
写在谁的事件里显示的就是谁的Caption
2005-02-01 16:07:17 D10.天地弦(185511468)
B6你换个试试
2005-02-01 16:07:22 D10.天地弦(185511468)
嗯,
2005-02-01 16:07:24 布袋猫(6148012)
有意思,呵呵
2005-02-01 16:07:24 D10.天地弦(185511468)
咱了
2005-02-01 16:07:24 B6.银狼(43225570)
好
2005-02-01 16:07:41 D10.天地弦(185511468)
是不是这样
2005-02-01 16:07:58 B6.银狼(43225570)
有意思,是的
2005-02-01 16:08:12 D10.天地弦(185511468)
点击的时候有Push一个实例进去
2005-02-01 16:08:17 B6.银狼(43225570)
而且没有该有的退出时的错误
2005-02-01 16:08:27 B6.银狼(43225570)
哦,对,不该有错误
2005-02-01 16:08:33 D10.天地弦(185511468)
B刚好和这个实例都有Caption属性
2005-02-01 16:08:48 D10.天地弦(185511468)
是不是
2005-02-01 16:08:51 B6.银狼(43225570)
要是没有呢
2005-02-01 16:09:06 D10.天地弦(185511468)
error
2005-02-01 16:09:22 A3.武稀松(42088303)
但是你把编译选项的优化选项去掉,重新Build以后在看看执行什么结果
2005-02-01 16:10:05 D10.天地弦(185511468)
出错
2005-02-01 16:10:06 B6.银狼(43225570)
哪个是优化啊,不认识
2005-02-01 16:10:10 布袋猫(6148012)
Tedit没有CAPTION属性
2005-02-01 16:10:23 布袋猫(6148012)
显示的是TEXT内容
2005-02-01 16:10:27 D8 。飘尘(43745429)
武松做一下总结了
2005-02-01 16:10:38 兰铃子(105351942)
/
2005-02-01 16:10:43 兰铃子(105351942)
?
2005-02-01 16:10:47 A3.武稀松(42088303)
没啥总结的.都讲完了
2005-02-01 16:10:59 D10.天地弦(185511468)
[图片]
2005-02-01 16:11:17 乾隆(7891551)
天讲了些太高深的东西,对我来说现在都用不到,55555555555
2005-02-01 16:11:39 乾隆(7891551)
给我们讲讲基础的东西好吗
2005-02-01 16:11:47 A3.武稀松(42088303)
今天主要是用汇编把各个调用方式写一遍,给大家一个更具体的认识而已
2005-02-01 16:12:09 D8 。飘尘(43745429)
记录太多了。偶看不过来了
2005-02-01 16:12:25 D10.天地弦(185511468)
3哥,是不是那个Integrate debugging编译优化?
2005-02-01 16:12:25 兰铃子(105351942)
?
2005-02-01 16:12:39 A3.武稀松(42088303)
[图片]
2005-02-01 16:12:41 D10.天地弦(185511468)
不是
2005-02-01 16:12:43 D10.天地弦(185511468)
搞错了
2005-02-01 16:12:47 乾隆(7891551)
D10出来,给我把类讲下吧,让群里的菜鸟也能消化点食
2005-02-01 16:12:53 A3.武稀松(42088303)
把这个选项去掉.大家重新Build再看看刚才的代码
2005-02-01 16:13:26 D10.天地弦(185511468)
嗯
2005-02-01 16:13:27 B6.银狼(43225570)
可以编译,运行时错误
2005-02-01 16:13:29 D10.天地弦(185511468)
出错
2005-02-01 16:13:46 B6.银狼(43225570)
是个地址错误
2005-02-01 16:13:49 D10.天地弦(185511468)
乾隆(7891551) 16:12:47
D10出来,给我把类讲下吧,让群里的菜鸟也能消化点食 ==>有讲过
2005-02-01 16:14:10 D8 。飘尘(43745429)
D10氢DEMO发一个过来了
2005-02-01 16:14:17 D10.天地弦(185511468)
[:L]
2005-02-01 16:14:21 乾隆(7891551)
可我没听到过啊,照顾下新来的偶啊
2005-02-01 16:14:22 D10.天地弦(185511468)
群的共享里有
2005-02-01 16:14:30 A3.武稀松(42088303)
飘尘,群共享里面有的
2005-02-01 16:14:30 D10.天地弦(185511468)
D8
2005-02-01 16:14:31 B6.银狼(43225570)
这个是什么东西
2005-02-01 16:14:28 B6.银狼(43225570)
[图片]
2005-02-01 16:14:39 B6.银狼(43225570)
帮我看看以前没有的
2005-02-01 16:14:39 D8 。飘尘(43745429)
我上不了了
2005-02-01 16:14:41 乾隆(7891551)
D10再给大家讲次吧,
2005-02-01 16:14:43 D10.天地弦(185511468)
咱这么大
2005-02-01 16:14:50 D10.天地弦(185511468)
[:L]
2005-02-01 16:14:52 B6.银狼(43225570)
delphi 里的
2005-02-01 16:15:01 D8 。飘尘(43745429)
传给了。我是繁休下面的
2005-02-01 16:15:05 B6.银狼(43225570)
就是今天你给我弄来弄去就出来了
2005-02-01 16:15:06 乾隆(7891551)
有没有这么同意我的的意见啊,同意的别说话
2005-02-01 16:15:13 D10.天地弦(185511468)
乾隆我传记录给你
2005-02-01 16:15:15 D8 。飘尘(43745429)
QQ不能用群共享了
2005-02-01 16:15:19 D10.天地弦(185511468)
OK
2005-02-01 16:15:23 乾隆(7891551)
好吧
2005-02-01 16:15:45 B6.银狼(43225570)
武大,你看到了么?
2005-02-01 16:15:49 乾隆(7891551)
我今天换了个QQ代理速度快了N多
2005-02-01 16:15:53 A3.武稀松(42088303)
[?]
2005-02-01 16:16:03 B6.银狼(43225570)
刚才我帖的大图,
2005-02-01 16:16:17 B6.银狼(43225570)
是D7里的,不知道怎么出来的
2005-02-01 16:16:25 B6.银狼(43225570)
我不喜欢它
2005-02-01 16:16:39 A3.武稀松(42088303)
大概B6安装了什么第三方的OTA工具
2005-02-01 16:16:49 B6.银狼(43225570)
OTA?
2005-02-01 16:17:18 B6.银狼(43225570)
以前没有的,就是今天和D10远程时,搞出来的
2005-02-01 16:17:26 D10.天地弦(185511468)
[:L]
2005-02-01 16:17:26 A3.武稀松(42088303)
Open Tools Api Delphi的IDE开发接口
2005-02-01 16:17:36 B6.银狼(43225570)
不知道怎么弄的
2005-02-01 16:17:54 D10.天地弦(185511468)
format c:/q
F:
2005-02-01 16:18:04 D10.天地弦(185511468)
cd system\win98
2005-02-01 16:18:03 B6.银狼(43225570)
A3.武稀松(42088303) 16:17:26
Open Tools Api Delphi的IDE开发接口 〈--没懂
2005-02-01 16:18:08 D10.天地弦(185511468)
setup
2005-02-01 16:18:07 A3.武稀松(42088303)
[shake]
2005-02-01 16:18:09 B6.银狼(43225570)
晕
2005-02-01 16:18:19 B6.银狼(43225570)
[xx]
2005-02-01 16:18:39 D10.天地弦(185511468)
[:L]
2005-02-01 16:18:42 D10.天地弦(185511468)
错了
2005-02-01 16:19:00 D10.天地弦(185511468)
cd system\win2k\i386
2005-02-01 16:19:03 D10.天地弦(185511468)
winnt
2005-02-01 16:20:04 D10.天地弦(185511468)
3哥,把你的记录传我一份
2005-02-01 16:20:13 D10.天地弦(185511468)
中间死了两次
2005-02-01 16:20:13 A3.武稀松(42088303)
等下
2005-02-01 16:20:28 D10.天地弦(185511468)
我整理上传
2005-02-01 16:21:25 D8 。飘尘(43745429)
记录给偶了
2005-02-01 16:21:40 A3.武稀松(42088303)
怎么导出从一定时间一后的记录
A3.武稀松(42088303) 16:30:23
我怀疑优化编译的时候最后一个调用的控件方法以后EAX没有被还原,所以再次调用那个没有被创建的类的的时候EAX还是以前的值,也就是对象是上一个被调用的对象.
B1.斜阳(249208513) 16:30:57
在Delphi中生成的汇编中,通常总是用EBX暂存Eax中的内容
A3.武稀松(42088303) 16:31:10
嗯
B1.斜阳(249208513) 16:31:49
而EBX通常不参与参数的传递,这样,在进入某一个函数的时候,ebx寄存器中的内容,有可能是上一个函数中的self
B2.TCP INFO(31329846) 16:32:11
这里 看到没
B2.TCP INFO(31329846) 16:32:22
[调试图片]
B2.TCP INFO(31329846) 16:32:43
mov eax,ebx
A3.武稀松(42088303) 16:32:44
但是如果编译优化选项去掉为什么就会报错
B1.斜阳(249208513) 16:32:47
不清楚Delphi怎么优化的,当声明一个类类型的变量的时候,都是用push ebx,而不是push 00
D8 。飘尘(43745429) 16:33:59
当声明一个类类型的变量的时
一个类类型?????
A3.武稀松(42088303) 16:34:09
类类型的变量
B1.斜阳(249208513) 16:34:17
这就倒是在临时变量的堆栈中,对于类类型的,其初值不是nil
A3.武稀松(42088303) 16:34:27
对
A3.武稀松(42088303) 16:34:44
我想B1说得是最正确地
B1.斜阳(249208513) 16:35:00
类
类型->数据类型是类的变量
B1.斜阳(249208513) 16:35:41
而因为在Delphi为类类型变量准备堆栈的时候是用push ebx
A3.武稀松(42088303) 16:35:42
类类型的变量很准确,
A3.武稀松(42088303) 16:36:30
B1说得对
B1.斜阳(249208513) 16:36:47
因此,在没有对ebx的内容进行修改的前提下,在引用堆栈中的类类型变量的时候,自然是直接使用ebx要不从堆栈中再计算一次要快
A3.武稀松(42088303) 16:36:47
应该是push ebx这里出的问题
B1.斜阳(249208513) 16:37:15
因此,在类试
var
a: TForm;
begin
ShowMessage(a.Caption)
end;
B1.斜阳(249208513) 16:37:20
这样的代码中
A3.武稀松(42088303) 16:38:01
A是上一个被调用对象
B1.斜阳(249208513) 16:38:20
对a.Caption的调用,其中的a这个标号,不是从堆栈中计算出来的一个地址,而是直接引用ebx中的内容
B1.斜阳(249208513) 16:38:31
呵呵,这是我的理解
B1.斜阳(249208513) 16:39:37
Button1Click这个函数虽然是Form中的函数,但是,却是Button1的事件响应函数,因此,这个函数是从Tbutton中调用的
D10.天地弦(185511468) 16:42:08
A3.武稀松(42088303) 16:30:23
我怀疑优化编译的时候最后一个调用的控件方法以后EAX没有被还原,所以再次调用那个没有被创建的类的的时候EAX还是以前的值,也就是对象是上一个被调用的对象. ==>我也这样认为
A3.武稀松(42088303) 16:40:29
B1.斜阳(249208513) 16:39:37
Button1Click这个函数虽然是Form中的函数,但是,却是Button1的事件响应函数,因此,这个函数是从Tbutton中调用的
----------------------------------------
最后一个被调用到的对象是Button1
B1.斜阳(249208513) 16:40:45
是的