删除用纯汇编编写的函数的序言
我使用的是 Delphi 2010。是否可以告诉 Delphi 不要为函数生成序言?我正在编写一些像这样的纯汇编函数:
procedure SomeAssembly; stdcall;
begin
asm
...
end;
end;
我想告诉 Delphi 不要为这个函数生成序言和尾声,就像 C++ 的 __declspec(naked) 功能一样。
所以没有人浪费时间,我不需要帮助让这些函数与序言一起工作;我已经可以做到了。这不仅带来很大的不便,而且会给维护带来巨大的麻烦。我必须手动检查编译器生成的序言以查看它们的长度,如果发生变化,我的程序将崩溃。
我还知道我可以将函数编写为字节数组中的一系列字节,但这比必须查找 Delphi 序言的长度还要糟糕。
I am using Delphi 2010. Is it possible to tell Delphi to not generate a prologue for a function? I'm writing some pure assembly functions like this:
procedure SomeAssembly; stdcall;
begin
asm
...
end;
end;
and I would like to tell Delphi not to generate a prologue and epilogue for this function, like C++'s __declspec(naked)
feature.
And so no one wastes their time, I don't need help getting these functions to work with the prologue; I can already do that. It's just a large inconvenience and will make maintenance an huge hassle. I'll have to manually inspect the prologues generated by the compiler to see their length, and if that changes, my program will crash.
I also know I can write the function as a series of bytes in a byte array, but that would be even worse than having to go find the length of Delphi's prologue.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
Delphi 不会为没有参数且使用注册调用约定声明的函数生成序言或尾声。如果您想要没有序言的函数,请将它们声明为零参数、寄存器调用约定函数。另外,跳过
begin
-end
块并直接进入汇编。由于您实际上对函数的性质撒了谎,因此调用它们可能会很棘手。如果您实现了一个函数,就像它接收参数并使用不同的调用约定一样,那么您必须确保编译器在调用站点知道这一点。为此,请声明一个函数指针,该指针反映函数的“真实”类型而不是声明的类型。例如,如果您的函数实际上是一个双参数 stdcall 函数,请声明如下内容:
现在,分配该变量,使其指向您的函数:
除了跳过序言和尾声之外,编译器还将生成不正确的
此函数的 RET
指令(由于调用约定不同),因此您必须确保在代码中使用ret 8
,而不是让编译器默认的ret
指令发生。如果您有一个可用的调试器,那么查找 Delphi 序言的长度是微不足道的:
Delphi doesn't generate prologues or epilogues for functions having no arguments and declared with the register calling convention. If you want functions without prologues, declare them as zero-argument, register-calling-convention functions. Also, skip the
begin
-end
block and go straight into assembly.Since you're effectively lying about the nature of the functions, calling them may be tricky. If you've implemented a function as though it received parameters and used a different calling convention, then you'll have to make sure the compiler knows about that at the call site. To do that, declare a function pointer that reflects the "real" type of your function instead of the declared type. For example, if your function is really a two-argument stdcall function, declare something like this:
Now, assign that variable so it points at your function:
In addition to skipping the prologue and epilogue, the compiler will generate the incorrect
RET
instruction for this function (because of the different calling convention), so you'll have to make sure you sayret 8
in your code instead of letting the compiler's defaultret
instruction occur.Finding the length of Delphi's prologue is trivial, if you have a working debugger:
根据 此 embarcadero docwiki 您可以跳过周围的
begin
和end
并且编译器将跳过其中的一些内容。但如果你真的想要纯汇编程序,为什么不将你的函数放入一个单独的汇编程序文件中,用 tasm 对其进行汇编(exe 名为 tasm32)并链接到它。然后,您将在 delphi 代码中使用assembler
指令。According to the this embarcadero docwiki you can skip the surrounding
begin
andend
and the compiler will skip some of it's stuff. But if you really want pure assembler, why not put your function into a separate assembler file, assemble it with tasm (the exe is named tasm32) and link to it. You'll then use theassembler
directive in the delphi code.不会
有窍门吗?
Doesn't
do the trick?