Delphi does not generate prologs or epilogues for functions that have no arguments and are declared using a register registry agreement. If you need functions without prologs, declare them as arguments with a null argument, call registration functions. Also, skip the begin - end block and go straight to the assembly.
procedure SomeAssembly; // register; (implied) asm // ... end;
Since you are effectively lying about the nature of functions, calling them can be difficult. If you implemented a function as if it were receiving parameters and using a different calling convention, you need to make sure that the compiler knows about it on the call site. To do this, declare a pointer to a function that reflects the "real" type of your function instead of the declared type. For example, if your function is really a function with two stdcall arguments, declare something like this:
type TSomeAssemblyFunc = function (Arg1: Integer; Arg2: PAnsiChar): Boolean; stdcall; var SomeAssemblyProc: TSomeAssemblyProc;
Now assign this variable so that it points to your function:
SomeAssemblyProc := TSomeAssemblyProc(@SomeAssembly); if SomeAssembly(2, 'foo') then ...
In addition to skipping the prolog and epilogue, the compiler will generate an invalid RET instruction for this function (due to a different calling convention), so you need to make sure you say ret 8 in your code instead of giving the compiler's default RET command .
Finding the length of the Delphi prolog is trivial if you have a working debugger:
- Set a breakpoint at the beginning of the function.
- Call the function.
- When the debugger stops at a breakpoint, switch to the CPU view.
- See the instructions that make up the prologue.
- Count the bytes displayed next to these instructions.
Rob kennedy
source share