gpt4 book ai didi

.net - JclDotNet,以及一些使用汇编程序的奇怪调用模式

转载 作者:行者123 更新时间:2023-12-03 19:23:25 31 4
gpt4 key购买 nike

我们有自己的粘合层代码thingamajig,它允许我们在我们的Win32 Delphi 程序中托管.NET 运行时。这使我们能够随着时间的推移逐步过渡到 .NET。

但是,我们时不时会遇到一些问题,昨天我在 SO 上看到了一个答案,其中提到了 Jcl 的 .NET 主机实现,所以我想看看是否有一些明显的差异。

原来有,但我不明白它是做什么的,为什么,以及我是否需要这样做。我当然会尝试它,但我非常希望其他了解这个奇怪代码背后原因的人告诉我它的作用。

随着时间的推移,我们可能会切换到使用 Jcl 实现,但由于我们即将发布,除非为了解决当前问题绝对有必要,否则在这个级别的代码进行大修是不合理的,所以请不要t 只是建议我们切换。

无论如何,不​​同之处在于它们如何调用 .NET 函数以加载和绑定(bind)到 .NET 运行时,基本上它们如何调用从 .NET dll 导出的函数。

这是我的代码:

type
TCorBindToRuntimeEx = function(pwszVersion: PWideChar;
pwszBuildFlavor: PWideChar;
startupFlags: DWord; rclsid, riid: PGUID;
out ppv: IUnknown): Integer; stdcall;
...
var
CorBindToRuntimeEx : TCorBindtoRuntimeEx = nil;
...
CorBindToRuntimeEx := GetProcAddress(Runtimehandle, 'CorBindToRuntimeEx');
...
clsid := CLASS_CorRuntimeHost;
iid := IID_ICorRuntimeHost;
rc := CorBindToRuntimeEx('v2.0.50727', 'wks', 0, @clsid,
@iid, UnkRuntimeEngine);

现在,这里我只是简单地使用 GetProcAddress 将导出函数的地址加载到一个变量中,输入为 stdcall函数指针,然后我调用它。这行得通,有点。正如我所说,在少数情况下会出现一些奇怪的错误消息。

好的,这是他们的代码,特别注意带有汇编代码的函数。
function CorBindToRuntimeEx(pwszVersion, pwszBuildFlavor: PWideChar;
startupFlags: DWORD; const rclsid: TCLSID; const riid: TIID;
out pv): HRESULT; stdcall;
{$EXTERNALSYM CorBindToRuntimeEx}
...
var
_CorBindToRuntimeEx: Pointer = nil;

function CorBindToRuntimeEx;
begin
GetProcedureAddress(_CorBindToRuntimeEx, mscoree_dll,
'CorBindToRuntimeEx');
asm
mov esp, ebp
pop ebp
jmp [_CorBindToRuntimeEx]
end;
end;
...
OleCheck(CorBindToRuntimeEx(PWideCharOrNil(ClrVer),
PWideChar(ClrHostFlavorNames[Flavor]), Flags,
CLASS_CorRuntimeHost, IID_ICorRuntimeHost,
FDefaultInterface));

请注意,我已经稍微重新格式化了代码以避免在 SO 上出现水平滚动条,但只是添加了一些换行符和一些缩进,代码是原样的。

最后的调用可能无关紧要,它基本上会传递我们所做的相同参数(注意我们传递 0 作为选项值,但我们也尝试使用 Jcl 代码使用的相同特定参数,问题仍然存在展示)。

所以,我的问题是,汇编代码是做什么的?我知道它在技术意义上是做什么的,我以前一直在编程汇编,所以它操纵堆栈指针。

问题是为什么它必须这样做。我只是不明白。

可能是堆栈帧不完全 stdcall毕竟?

今天请教我一些东西。

编辑 : 好的,相应地更改了我的代码,但我们的问题仍然存在,所以不是这样。看起来我毕竟会做一些 WinDbg 来挖掘第三方代码。

最佳答案

汇编代码删除 CorBindToRuntimeEx 的堆栈帧。
如果您调用 CorBindToRuntimeEx,所有参数都被插入堆栈(=> stdcall)。然后该函数调用 GetProcedureAddress 来初始化全局 _CorBindToRuntimeEx 变量,该变量现在指向“CorBindToRuntimeEx”函数。

GetProcedureAddress 返回后必须调用 _CorBindToRuntimeEx 函数。但是这里我们有一个问题。 Delphi 自动在代码中添加了“push ebp; mov ebp,esp”(“begin”所在的位置)。为了删除该堆栈帧,使用了“mov esp,ebp; pop ebp”。 “jmp [_CorBindToRuntimeEx]”然后将执行指针设置为 _CorBindToRuntimeEx 函数,然后该函数使用来自我们的 CorBindToRuntimeEx 函数的返回地址。

关于.net - JclDotNet,以及一些使用汇编程序的奇怪调用模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/776174/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com