免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
Inline Assembler in Delphi (VI) Calling external procedures

Inline Assembler in Delphi (VI) Calling external procedures

 

Inline Assembler in Delphi (VI)
Calling external procedures


By Ernesto De Spirito <edspirito@latiumsoftware.com>

API functions and the Stdcall calling convention



API functions are called transparently from inline assembler with the CALL statement. However, we must take into account that passing parameters to API functions is different since they normally use the Stdcall calling convention, instead of the Register calling convention, which is the one we've seen so far since it is the default convention.

In the Stdcall calling convention, all parameters are passed on the stack, from right to left, i.e. the last (rightmost) parameter is pushed first, and the first (leftmost) parameter is pushed last, so it'll the one on top of the stack. Here is an example of a procedure that calls an API function:

  procedure HideForm(Handle: THandle);
  // Windows.ShowWindow(Handle, SW_HIDE);
  asm
    push SW_HIDE               // push 0    // Pass second parameter
    push Handle                // push eax  // Pass first parameter
    call Windows.ShowWindow    // Call the API ShowWindow
  end;

If we have to call a method that uses the stdcall convention, remember that the Self pointer is an invisible first parameter, so it'll be pushed last on the stack.

If we have to write functions that use the stdcall convention, there's nothing special we should worry about. The compiler will always create a stack frame and references to parameter names will be converted into addresses relative to the base pointer:

  function AddAndMultiply(i1, i2, i3: integer): integer; stdcall;
  asm  // ==> push ebp; mov ebp, esp
    // Result := (i1 + i2) * i3;
    mov eax, i1   // mov eax, [ebp+8]
    add eax, i2   // add eax, [ebp+12]
    imul i3       // imul [ebp+16]
  end; // ==> pop ebp; ret 12

This is a sample call for the function:

  asm
    // a := AddAndMultiply(1, 2, 3); // result should be 9
    push 3
    push 2
    push 1
    call AddAndMultiply
    mov a, eax
  end;

After entering the function, the stack would look like this:

  |                |
  +----------------+
  |    Old EBP     |  [EBP], [ESP]
  +----------------+
  | Return Address |  [EBP+4]
  +----------------+
  |     i1 = 1     |  [EBP+8]
  +----------------+
  |     i2 = 2     |  [EBP+12]
  +----------------+
  |     i3 = 3     |  [EBP+16]
  +----------------+
  |                |


C/C++ libraries and the Cdecl calling convention



Sometimes we need to access functions in object files (.OBJ), static libraries (.LIB) or dynamic libraries (.DLL) written in C or C++, and quite frequently these functions use the Cdecl calling convention. It is very much like the Stdcall convention, but the stack should be cleaned by the caller, i.e., the caller should pop the parameters it pushed, or -better- increment the stack pointer.

  function AddAndMultiply(i1, i2, i3: integer): integer; cdecl;
  asm  // ==> push ebp; mov ebp, esp
    // Result := (i1 + i2) * i3;
    mov eax, i1   // mov eax, [ebp+8]
    add eax, i2   // add eax, [ebp+12]
    imul i3       // imul [ebp+16]
  end; // ==> pop ebp; ret

Notice in the comment for the last line that the function doesn't move the stack pointer as it did in the previous example that used the Stdcall convention, so the caller is the one who is responsible for that. This is a sample call for the function:

  asm
    // a := AddAndMultiply(1, 2, 3); // should be 9
    push 3
    push 2
    push 1
    call AddAndMultiply
    add esp, 12           // clean the stack
    mov a, eax
  end;

Notice that if the parameters were of type Byte instead of Integer, we should still move the stack pointer by 12 bytes since each parameter would take 32 bits (4 bytes) anyway.


The Pascal calling convention



Many C/C++ programmers prefer the Pascal calling convention over the Cdecl calling convention because it is more compact and also faster since the called function clears the stack in the RET statement, as it happens in the Stdcall convention. The Pascal convention is like the Stdcall convention, but parameters are passed left-to-right instead of right-to-left, i.e. the first (leftmost) parameter is pushed first, and the last (rightmost) parameter is pushed last:

  function AddAndMultiply(i1, i2, i3: integer): integer; pascal;
  asm  // ==> push ebp; mov ebp, esp
    // Result := (i1 + i2) * i3;
    mov eax, i1   // mov eax, [ebp+16]
    add eax, i2   // add eax, [ebp+12]
    imul i3       // imul [ebp+8]
  end; // ==> pop ebp; ret 12

Notice how the addresses of the parameters are translated different than in the previous examples.

This is a sample call for the function:

  asm
    // a := AddAndMultiply(1, 2, 3); // should be 9
    push 1
    push 2
    push 3
    call AddAndMultiply
    mov a, eax
  end;

After entering the function, the stack would look like this:

  |                |
  +----------------+
  |      EBP       |  [EBP], [ESP]
  +----------------+
  | Return Address |  [EBP+4]
  +----------------+
  |     i3 = 3     |  [EBP+8]
  +----------------+
  |     i2 = 2     |  [EBP+12]
  +----------------+
  |     i1 = 1     |  [EBP+16]
  +----------------+
  |                |




Previous: Inline Assembler in Delphi (V) - Objects
Next: Inline Assembler in Delphi (VII) - 128-bit integer arithmetic


分類: BASM Delphi
博主上一篇:Inline Assembler in Delphi (V) An Introdunction to Objects
博主下一篇:Inline Assembler in Delphi (II) ANSI strings
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Debug Tutorial Part 2: The Stack
The details of C function stack (and heap) operation when function call is made (caller) and returne
論函數(shù)調(diào)用約定
DLL中調(diào)用約定和名稱修飾(一)
函數(shù)調(diào)用方式介紹
函數(shù)調(diào)用約定和堆棧
更多類似文章 >>
生活服務(wù)
分享 收藏 導長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服