zoukankan      html  css  js  c++  java
  • Delphi 实现C语言函数调用

    在X86下,C语言函数调用,使将参数从右到左压入堆栈,栈指针减小,最后一个参数压入后,栈指针指向最后一个参数

    因此我们可以通过增加栈指针,读取所有的参数,X86CPU的堆栈是4字节对齐,也就是说字节性或者字型参数都是压入4

    字节。

    type  
      TArgPtr =record
      private
        FArgPtr: PByte;classfunction Align(Ptr: Pointer; Align: Integer): Pointer; static;
      public
        constructor Create(LastArg: Pointer; Size: Integer);
      
    // Read bytes, signed words etc. using Int32
    // Make an unsigned version if necessary.
    function ReadInt32: Integer;
    // Exact floating-point semantics depend on C compiler.
    // Delphi compiler passes Extended as 10-byte float; most C
    // compilers pass all floating-point values as 8-byte floats.
    function ReadDouble: Double;
    function ReadExtended: Extended;
    function
    ReadPChar: PChar;
    procedure
    ReadArg(var Arg; Size: Integer);
    end;

    constructor
    TArgPtr.Create(LastArg: Pointer; Size: Integer);
    begin
    FArgPtr := LastArg;// 32-bit x86 stack is generally 4-byte aligned FArgPtr := Align(FArgPtr + Size,4);
    end;
    classfunction TArgPtr.Align(Ptr: Pointer; Align: Integer): Pointer;
    begin
    Integer(Result):=(Integer(Ptr)+ Align -1)and not(Align -1);
    end;
    function TArgPtr.ReadInt32: Integer;
    begin ReadArg(Result, SizeOf(Integer));
    end;
    function TArgPtr.ReadDouble: Double;
    begin
    ReadArg(Result, SizeOf(Double));
    end;
    function TArgPtr.ReadExtended: Extended;
    begin ReadArg(Result, SizeOf(Extended));
    end;
    function TArgPtr.ReadPChar: PChar;
    begin
    ReadArg(Result, SizeOf(PChar));
    end;
    procedure TArgPtr.ReadArg(var Arg; Size: Integer);
    begin Move(FArgPtr^, Arg, Size); FArgPtr := Align(FArgPtr + Size,4);
    end
    ;
    procedure Dump(const types:string); cdecl;
    var ap: TArgPtr; cp: PChar;
    begin cp := PChar(types); ap := TArgPtr.Create(@types, SizeOf(string));
     
    while True do
    begin
    case cp^ of
    #0:begin Writeln; Exit;
    end;
    'i': Write(ap.ReadInt32,' ');
    'd': Write(ap.ReadDouble,' ');
    'e'
    : Write(ap.ReadExtended,' ');
    's'
    : Write(ap.ReadPChar,' ');
    else Writeln('Unknown format'); Exit;
    end; Inc(cp);
    end;
    end;
    type PDump =procedure(const types:string) cdecl varargs;
    var MyDump: PDump;
    function AsDouble(e: Extended): Double;
    begin Result := e;
    end
    ;
    function AsSingle(e: Extended): Single;
    begin Result := e;
    end;
    procedure Go;
    begin MyDump :=@Dump; MyDump('iii',10,20,30); MyDump('sss','foo','bar','baz');// Looks like Delphi passes Extended in byte-aligned// stack offset, very strange; thus this doesn't work. MyDump('e',2.0);// These two are more reliable. MyDump('d', AsDouble(2));// Singles passed as 8-byte floats. MyDump('d', AsSingle(2));
    end;
    begin Go;
    end.

     

  • 相关阅读:
    四大组件的工作过程
    理解Window和WindowManager
    Android中的动画
    View的工作原理
    62、滑动窗口的最大值
    61、数据流中的中位数
    60、二叉搜索树的第k个结点
    59、序列化二叉树
    58、把二叉树打印成多行
    57、按之字形顺序打印二叉树
  • 原文地址:https://www.cnblogs.com/hezihang/p/3072880.html
Copyright © 2011-2022 走看看