技術交流,dh講解.
本隨筆,就自己一心得+筆記,而自己水平有限,所以本文也可能是水文.哈哈
講解前先來個**:有條件的朋友可以看加密解密(第三版)一書,哈哈,我書還是買了一些的.
方式傳值方向
傳值位置
誰來平衡堆疊
備註 _cdecl
從右到左
直接壓棧
呼叫者預設c++的
_stdcall
從右到左
直接壓棧
函式本身
win32 api
register
從左到右
adc暫存器然後壓棧
函式本身
delphi預設的
pascal
從左到右
直接壓棧
函式本身
safecall
同stdcall
不同呼叫有什麼區別呢?
function teststdcall(a,b:integer):integer ;stdcall;**都一樣,我們來看看執行時候有什麼不一樣的地方呢?var c:integer;
begin
c:=a+b;
if c>2*a then
dec(c,b)
else
dec(c,a);
result:=c;
end;
function testcdecl(a,b:integer):integer ;cdecl;
var c:integer;
begin
c:=a+b;
if c>2*a then
dec(c,b)
else
dec(c,a);
result:=c;
end;
function testregister(a,b:integer):integer ;
var c:integer;
begin
c:=a+b;
if c>2*a then
dec(c, b)
else
dec(c, a);
result:= c;
end;
procedure tform4.formcreate(sender: tobject);
var c: integer;
begin
c:= teststdcall(5, 6);
showmessage(inttostr(c));
c:= testcdecl(5, 6);
showmessage(inttostr(c));
c:= testregister(5, 6);
showmessage(inttostr(c));
end;
第乙個teststdcall:
我們看見先壓6再壓5,也就是從右到左壓棧.函式內部:
先將棧裡面的引數取出來放到ecx和edx中,最後清除棧ret 8;
stdcall很明顯了.
接下來看cdecl呼叫方式吧.
也是先壓6再壓5,但是我們看到最後面add esp,8,這個就是平衡棧了,因為我們壓入了2個integer,8個位元組.
函式內部:
還是先從棧裡面去引數到暫存器,最後直接ret咯.
接下來是delphi預設的方式:
將5傳入eax,6傳入edx,它這裡雖然現傳的6,但是我們要注意暫存器的順序應該是 eax,edx,ecx,如果還有多餘的引數再壓棧.
函式內部:
暈這個例子沒有選好,因為引數沒有用到棧,所以不存在棧平衡,我改一下...
從壓棧的順序我們再一次看出來了,是從左到右的,先壓的8.
釋放引數壓棧用的空間,ret 8;
最後改一下,來看看pascal呼叫方式,這個是delphi1.0時候用的:
從左到右壓棧的.
細心的朋友會發現這次沒有講棧裡面東西取到暫存器中去,主要因為這次運算太簡單了.哈哈,最後自己清除壓的棧.
為什麼要了解這些?
答案肯定是為了程式能夠正常的工作了.這個問題...
如果宣告和呼叫的方式不一樣會怎麼樣?
1 走錯路.如果只是從左到右和從右到左弄錯了,程式能執行,只是引數a被當成引數b來用,也就是結果可能不對.
2 走上不歸路.因為我們知道堆疊裡面儲存了函式的返回位址這些,但是如果我們呼叫方式不一樣就可能造成堆疊被破壞了,程式無法正常返回,就會報錯了.
ok,個人理解.
delphi 呼叫dll兩種方式
1 外部宣告 在delphi中外部宣告是訪問外部例程最容易和最常用的方式,有兩種宣告方式 通過名字 通過索引號。舉例如下 在mydll.dll中有兩個函式和乙個過程,則其外部宣告可以寫成 function test1 integer external mydll 直接通過名稱呼叫test1 注意名稱...
delphi呼叫webservice服務
我用delphi的thttprio控制項呼叫了c 寫的webservice。下面是我除錯時遇到的一些問題 注意末尾的 wsdl 不能少。要不可能會說找不到。2,設定thttprio控制項的屬性 開始把賦給了wsdllocation屬性。連線時總是報錯。後來賦給url屬性,就不報錯了。3,傳遞引數是w...
DELPHI儲存過程呼叫
網上對該問題的帖子很多,但是經常不是很全面,筆者在使用時也遇到了很多實際問題,比如引數不存在啊 型別沒有引用啊等等。下面我盡量細緻地來通過例子實現一下,如果還有不正確的地方,希望得到高手指點,有興趣的可以和我一同 zyf0808 yeah.net 首先,我們使用一種簡單的方式,即通過控制項的方式來定...