} } }

    Delphi 实现C说话函数调用

    添加时间:2013-5-14 点击量:

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


    是以我们可以经由过程增长栈指针,读取所有的参数,X86CPU的客栈是4字节对齐,也就是说字节性或者字型参数都是压入4


    字节。


    type  
    
    TArgPtr
    =record
    private
    FArgPtr
    : PByte;classfunction AlignPtr: Pointer; Align: Integer): Pointer; static;
    public
    constructor CreateLastArg: 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
    ReadArgvar Arg; Size: Integer);
    end;

    constructor
    TArgPtr.CreateLastArg: Pointer; Size: Integer);
    begin

    FArgPtr
    := LastArg;// 32-bit x86 stack is generally 4-byte aligned
    FArgPtr
    := AlignFArgPtr + Size4);
    end;
    classfunction TArgPtr.AlignPtr: Pointer; Align: Integer): Pointer;
    begin

    Integer
    Result:=IntegerPtr+ Align -1and notAlign -1);
    end;
    function TArgPtr.ReadInt32: Integer;
    begin
    ReadArg
    Result SizeOfInteger));
    end;
    function TArgPtr.ReadDouble: Double;
    begin

    ReadArg
    Result SizeOfDouble));
    end;
    function TArgPtr.ReadExtended: Extended;
    begin
    ReadArg
    Result SizeOfExtended));
    end;
    function TArgPtr.ReadPChar: PChar;
    begin

    ReadArg
    Result SizeOfPChar));
    end;
    procedure TArgPtr.ReadArgvar Arg; Size: Integer);
    begin
    Move
    FArgPtr^, Arg Size);
    FArgPtr
    := AlignFArgPtr + Size4);
    end
    ;
    procedure Dumpconst types:string); cdecl;
    var
    ap
    : TArgPtr;
    cp
    : PChar;
    begin
    cp
    := PChartypes);
    ap
    := TArgPtr.Create(@types SizeOfstring));
     
    while True do
    begin
    case cp^ of
    0:begin
    Writeln
    ;
    Exit
    ;
    end;
    i: Writeap.ReadInt32 );
    d: Writeap.ReadDouble );
    e
    : Writeap.ReadExtended );
    s
    : Writeap.ReadPChar );
    else
    Writeln
    Unknown format);
    Exit
    ;
    end;
    Inc
    cp);
    end;
    end;
    type
    PDump
    =procedureconst types:string cdecl varargs;
    var
    MyDump
    : PDump;
    function AsDoublee: Extended): Double;
    begin
    Result
    := e;
    end
    ;
    function AsSinglee: Extended): Single;
    begin
    Result
    := e;
    end;
    procedure Go;
    begin
    MyDump
    :=Dump;

    MyDump
    iii102030);
    MyDump
    sssfoobarbaz);// Looks like Delphi passes Extended in byte-aligned// stack offset, very strange; thus this doesnt work.
    MyDump
    e2.0);// These two are more reliable.
    MyDump
    d AsDouble2));// Singles passed as 8-byte floats.
    MyDump
    d AsSingle2));
    end;
    begin
    Go
    ;
    end.

     

    文艺不是炫耀,不是花哨空洞的文字堆砌,不是一张又一张的逆光照片,不是将旅行的意义转化为名牌包和明信片的物质展示;很多时候它甚至完全不美——它嘶吼、扭曲,它会痛苦地抽搐,它常常无言地沉默。——艾小柯《文艺是一种信仰》
    分享到: