Delphi에서 매개 변수의 전달과 함수 값의 반환

12272 단어
델피의 매개 변수의 전달과 함수 값에 대한 반환 선언: 고수들은 이미 알고 있었을 뿐만 아니라, 쓸 가치가 없었을 뿐이다.진정한 고수는 하나보다 더 깊게 잠재되어 있다. 우연히 이런 반찬만 더 작은 반찬에 글을 써서 줄 뿐이다.고수가 볼 때에는 큰 이빨을 잘 막고 많이 가르쳐 주십시오.반찬 동포 여러분께서 DELPHI 프로그램 해독에 대해 어떤 견해를 가지고 계신지 모르겠지만, 어쨌든 제 느낌은 한마디로 이상합니다.여러분들이 가장 먼저 겪으신 문제는 아마도 모두:저는 GetDlgItemInt,GetDlgItemText,GetWindowText를 내렸는데...왜 아무것도 끊이지 않고 심지어는 Hmemcpy조차도 작용하지 않습니까?허허, 여기서 보람의 사람들이 일부러 M달러와 맞서려고 하는 것을 알 수 있다. 신선한 것을 만들어내지 않으면 안 된다.이번에는 DLEPHI에서 함수(프로세스) 매개 변수의 전달이 어떻게 진행되는지 살펴보겠습니다.WinAPI가 사용하는 호출 약정은StdCall, 즉 함수Func(arg1,agr2,agr3,arg4)를 호출하는 것을 알고 있습니다. 당신은pusharg4,pusharg3,pusharg2,pusharg1,callFunc가 필요합니다.VC++에서도 이런 형식이기 때문에 한 함수에 몇 개의 매개 변수가 있어 매우 직관적으로 볼 수 있다.그런데 DELPHI에서 이상해요. 한 CALL 앞에서는 PUSH 하나도 안 보일 수도 있어요. 어떻게 된 거예요?내 말을 천천히 들어라.DELPHI의 호출 약정에는 StdCall, Cdecl, Safecall, Pascal, Register 등 몇 가지 방식이 있는데 DELPHI의 기본 방식은 Register(왜 Pascal이 아니야?)이다.Register 방식은 가능한 한 레지스터를 사용하여 파라미터를 전달하고 창고의 조작을 줄여 속도를 높이는 것이다.구체적인 상황은 어떠한가. 예를 들면 먼저: FORM에 BUTTON을 놓고 두 번 눌러서 코드를 쓰면 다음과 같다.
  :
function add1(a:Integer):Integer;    //    
begin
     add1:=a+a;
end;

function add2(a,b:Integer):Integer;    //    
begin
     add2:=a+b;
end;

function add3(a,b,c:Integer):Integer;    //    
begin
     add3:=a+b+c;
end;

function add4(a,b,c,d:Integer):Integer;    //    
begin
     add4:=a+b+c+d;
end;

function add5(a,b,c,d,e:Integer):Integer;  //    
begin
     add5:=a+b+c+d+e;
end;

function add6:Integer;        //        
var local1,local2,local3,local4,local5:Integer;
begin
     local1:=1;
     local2:=2;
     local3:=3;
     local4:=4;
     local5:=5;
     add6:=local1+local2+local3+local4+local5;
end;

function add7(a,b,c,d,e:Integer):Integer;  //  result   
begin
     result:=a+b+c+d+e;
end;

function add8(a,b,c,d,e:Integer):Integer;StdCall;//StdCall    
begin
     add8:=a+b+c+d+e;
end;

procedure TForm1.Button1Click(Sender: TObject);
var a,b,c,d,e:Integer;
    s1,s2,s3,s4,s5,s6,s7,s8,s:Integer;
begin
     a:=1; b:=2; c:=3; d:=4; e:=5;
     s1:=add1(a);
     s2:=add2(a,b);
     s3:=add3(a,b,c);
     s4:=add4(a,b,c,d);
     s5:=add5(a,b,c,d,e);
     s6:=add6;
     s7:=add7(a,b,c,d,e);
     s8:=add8(a,b,c,d,e);
     s:=s1+s2+s3+s4+s5+s6+s7+s8;      //        
     MessageDlg(IntToStr(s),mtConfirmation,[mbOK],0);  //              
end;

DEDE를 사용하여 이 Button1Click의 내용을 거꾸로 보십시오.
  :
004403EC   55                     push    ebp
004403ED   8BEC                   mov     ebp, esp
004403EF   83C4D8                 add     esp, -$28    ;         
004403F2   53                     push    ebx
004403F3   56                     push    esi
004403F4   57                     push    edi
004403F5   33C9                   xor     ecx, ecx
004403F7   894DD8                 mov     [ebp-$28], ecx
004403FA   33C0                   xor     eax, eax
004403FC   55                     push    ebp

* Possible String Reference to: ' -? _^[ ]?
|
004403FD   68E9044400             push    $004404E9

***** TRY
|
00440402   64FF30                 push    dword ptr fs:[eax]  ;  DELPHI     
00440405   648920                 mov     fs:[eax], esp    ;        VCL    SEH
00440408   BB01000000             mov     ebx, $00000001  ;a:=1
0044040D   BE02000000             mov     esi, $00000002  ;b:=2
00440412   BF03000000             mov     edi, $00000003  ;c:=3
00440417   C745FC04000000         mov     dword ptr [ebp-$04], $00000004  ;d:=4
0044041E   C745F805000000         mov     dword ptr [ebp-$08], $00000005  ;e:=5

    DELPHI     , EBX,ESI,EDI           ,       [ebp-xx],
              ,DELPHI            。

00440425   8BC3                   mov     eax, ebx    ;  add1    ,  PUSH 

* Reference to : TForm1.Proc_00440360()
|
00440427   E834FFFFFF             call    00440360    ;CALL add1

{
  00440360   03C0                   add     eax, eax
  00440362   C3                     ret      ;       
}

0044042C   8945F4                 mov     [ebp-$0C], eax  ;s1:=add1(a)
0044042F   8BD6                   mov     edx, esi    ;add2   EDX=2
00440431   8BC3                   mov     eax, ebx    ;add2   EAX=1

* Reference to : TForm1.Proc_00440364()
|
00440433   E82CFFFFFF             call    00440364    ;CALL add2

{
  00440364   03D0                   add     edx, eax  
  00440366   8BC2                   mov     eax, edx
  00440368   C3                     ret
}

00440438   8945F0                 mov     [ebp-$10], eax  ;s2:=add2(a,b)
0044043B   8BCF                   mov     ecx, edi    ;add3   ECX=3
0044043D   8BD6                   mov     edx, esi    ;EDX=2
0044043F   8BC3                   mov     eax, ebx    ;EAX=1

* Reference to : TForm1.Proc_0044036C()
|
00440441   E826FFFFFF             call    0044036C    ;CALL add3

{
  0044036C   03D0                   add     edx, eax
  0044036E   03CA                   add     ecx, edx
  00440370   8BC1                   mov     eax, ecx
  00440372   C3                     ret
}

00440446   8945EC                 mov     [ebp-$14], eax  ;s3:=add3(a,b,c)
00440449   8B45FC                 mov     eax, [ebp-$04]  ;[EBP-4]=4
0044044C   50                     push    eax      ;    PUSH  
0044044D   8BCF                   mov     ecx, edi    ;ECX=3
0044044F   8BD6                   mov     edx, esi    ;EDX=2
00440451   8BC3                   mov     eax, ebx    ;EAX=1

* Reference to : TForm1.Proc_00440374()
|
00440453   E81CFFFFFF             call    00440374    ;CALL add4

{
  00440374   55                     push    ebp
  00440375   8BEC                   mov     ebp, esp  ;  C      
  00440377   03D0                   add     edx, eax
  00440379   03CA                   add     ecx, edx
  0044037B   034D08                 add     ecx, [ebp+$08];[EBP+8]         
  0044037E   8BC1                   mov     eax, ecx  ;  [EBP+8]      
  00440380   5D                     pop     ebp
  00440381   C20400                 ret     $0004
}

00440458   8945E8                 mov     [ebp-$18], eax  ;s4:=add4(a,b,c,d)
0044045B   8B45FC                 mov     eax, [ebp-$04]  ;[EBP-4]=4
0044045E   50                     push    eax      ;  :           
0044045F   8B45F8                 mov     eax, [ebp-$08]  ;[EBP-8]=5
00440462   50                     push    eax      ;        ,Pascal    
00440463   8BCF                   mov     ecx, edi    ;ECX=3
00440465   8BD6                   mov     edx, esi    ;EDX=2
00440467   8BC3                   mov     eax, ebx    ;EAX=1

* Reference to : TForm1.Proc_00440384()
|
00440469   E816FFFFFF             call    00440384    ;CALL add5(a,b,c,d,e)
0044046E   8945E4                 mov     [ebp-$1C], eax  ;s5=add5(a,b,c,d,e)

* Reference to : TForm1.Proc_00440398()
|
00440471   E822FFFFFF             call    00440398    ;add6   DLEPHI        

{
  00440398   53                     push    ebx
  00440399   56                     push    esi
  0044039A   B801000000             mov     eax, $00000001
  0044039F   BA02000000             mov     edx, $00000002
  004403A4   B903000000             mov     ecx, $00000003
  004403A9   BB04000000             mov     ebx, $00000004
  004403AE   BE05000000             mov     esi, $00000005;  ,      
  004403B3   03D0                   add     edx, eax  ;            
  004403B5   03CA                   add     ecx, edx  ;               
  004403B7   03D9                   add     ebx, ecx  ;        
  004403B9   03F3                   add     esi, ebx
  004403BB   8BC6                   mov     eax, esi
  004403BD   5E                     pop     esi
  004403BE   5B                     pop     ebx
  004403BF   C3                     ret
}

00440476   8945E0                 mov     [ebp-$20], eax
00440479   8B45FC                 mov     eax, [ebp-$04]
0044047C   50                     push    eax
0044047D   8B45F8                 mov     eax, [ebp-$08]
00440480   50                     push    eax
00440481   8BCF                   mov     ecx, edi
00440483   8BD6                   mov     edx, esi
00440485   8BC3                   mov     eax, ebx

* Reference to : TForm1.Proc_004403C0()        ;     result      
|
00440487   E834FFFFFF             call    004403C0    ;   add5   ,   
0044048C   8945DC                 mov     [ebp-$24], eax
0044048F   8B45F8                 mov     eax, [ebp-$08]
00440492   50                     push    eax      ;PUSH 5
00440493   8B45FC                 mov     eax, [ebp-$04]
00440496   50                     push    eax      ;PUSH 4
00440497   57                     push    edi      ;PUSH 3
00440498   56                     push    esi      ;PUSH 2
00440499   53                     push    ebx      ;PUSH 1

* Reference to : TForm1.Proc_004403D4()
|
0044049A   E835FFFFFF             call    004403D4  ;      ,     StdCall  

{
  004403D4   55                     push    ebp
  004403D5   8BEC                   mov     ebp, esp
  004403D7   8B4508                 mov     eax, [ebp+$08]
  004403DA   03450C                 add     eax, [ebp+$0C]
  004403DD   034510                 add     eax, [ebp+$10]
  004403E0   034514                 add     eax, [ebp+$14]
  004403E3   034518                 add     eax, [ebp+$18]
  004403E6   5D                     pop     ebp
  004403E7   C21400                 ret     $0014    ;           
}

* Reference to Form1
|
0044049F   8B5DF4                 mov     ebx, [ebp-$0C]
004404A2   035DF0                 add     ebx, [ebp-$10]
004404A5   035DEC                 add     ebx, [ebp-$14]
004404A8   035DE8                 add     ebx, [ebp-$18]
004404AB   035DE4                 add     ebx, [ebp-$1C]
004404AE   035DE0                 add     ebx, [ebp-$20]
004404B1   035DDC                 add     ebx, [ebp-$24]
004404B4   03D8                   add     ebx, eax    ;   

........다음은 쓰지 않겠습니다. 특히 마지막으로 델피치가 두 개의 RET를 만들어서 왔다 갔다 하는 것도 델피치의 특색이라고 할 수 있습니다.위에서 말한 것은 자신이 정의한 함수인데 만약에 VCL 라이브러리의 동쪽을 사용한다면 때로는 더욱 영문을 알 수 없을 때가 있다.예: FORM을 만들고 BUTTON을 놓고 EDIT를 넣는다. 코드는 다음과 같다.
  :
procedure TForm1.Button1Click(Sender: TObject);
begin
     MessageDlg(edit1.text,mtConfirmation,[mbOK],0);
end;

허허 너무 간단하지 않아요? DEDE로 거꾸로 해요. (관건적인 부분만 썼어요)
  :
004417BE   6A00                   push    $00    ;    MessageDlg      ,   
004417C0   8D55FC                 lea     edx, [ebp-$04];??    ??

* Reference to control TForm1.Edit1 : TEdit
|
004417C3   8B83C8020000           mov     eax, [ebx+$02C8]  ;    GetText   TControl 
                ;    Reference
* Reference to: controls.TControl.GetText(TControl):TCaption;
|
004417C9   E8D619FEFF             call    004231A4  ;  EDIT   
004417CE   8B45FC                 mov     eax, [ebp-$04];             EAX
004417D1   668B0D00184400         mov     cx, word ptr [$00441800];       mtConfirmation
004417D8   B203                   mov     dl, $03  ;     [mbOK]

* Reference to: Dialogs.Proc_00441380
|
004417DA   E8A1FBFFFF             call    00441380  ;   MessageDlg
004417DF   33C0                   xor     eax, eax

위의 분석에 따르면 GetText는 EAX에 넣은 [ebx+02c8]의 매개 변수만 있을 것이다. 참고로 이것이EDIT1인데 함수의 반환값은?이 CALL을 실행한 후 EAX에는 없습니다. mov eax, [ebp-04]를 실행한 후에야 나타났습니다. 되돌아오는 값은 원래 [ebp-4]에 있습니다.그리고 엉뚱한lea edx, [ebp-04]를 찾아라. 내 위의 분석에 따르면 이것은GetText의 두 번째 파라미터를 표시해야 한다.근데 GetText는 매개 변수가 하나밖에 없잖아.이런 비교적 큰 구조의 함수를 되돌려야 한다. VC에서 자주 사용하는 방법은 하나의 바늘을 매개 변수로 전달하는 것이다. DLEPHI에서 나는 숨겨진 매개 변수를 만들었는지 추측한다. 위의GetText처럼 표면적으로 보면 TCAption을 되돌려주는 것이다. 실제로 이것은 EAX에 넣고 되돌려주는 것이 아니다.요약하자면DELPHI가 매개 변수에 대한 전달은 레지스터를 최대한 많이 이용하는 것이다. 일반적으로 첫 번째 매개 변수는 EAX를 사용하고 두 번째 매개 변수는 EDX를 사용하며 세 번째 매개 변수는 ECX를 사용한다. 세 개 매개 변수보다 많을 때 많이 나온 매개 변수는 왼쪽에서 오른쪽으로의PASCAL 방식으로 창고를 압축한다.함수의 반환값에 대해 때때로 성명에서 그 반환값이 TCAption 같은 것이라고 말하지만 실제로는 EAX에서 반환되지 않고 숨겨진 매개 변수를 저장하고 필요할 때 복사합니다.송이경(신지현): 그건 추측일 뿐이에요. 혹시 아시는 분 있으면 지적 좀 해주세요. 어차피 전 얼렁뚱땅 따라다녔는데 결과가 나오면 됐어요. 사실 자세히 따져보면 재미가 있어요.
전재 대상:https://www.cnblogs.com/okwary/archive/2008/12/24/1361330.html

좋은 웹페이지 즐겨찾기