MSVC:在64位代码中读取特定的64位或32位寄存器(例如R10)

MSVC: Reading a specific 64 or 32 bit register (e.g. R10) in 64 bit code?

本文关键字:64位 寄存器 32位 例如 R10 代码 读取 MSVC      更新时间:2023-10-16

MSVC是否有任何方法可以在普通C++函数中直接读取特定的64(或32)位寄存器?

例如,我可以通过任何内部函数或类似函数以某种方式读取r10的内容吗?


对于上下文:

我正在实现一个变参数函数(让我们称之为my_func),它需要将调用转发到另一个变函数,并在此过程中再添加一个参数(如果愿意,可以使用ID,任何数字类型都可以-例如,16、32或64位整数,都无关紧要)。

我需要在尽可能少的指令中进行转发,所以我不能在初始函数中处理可变列表,而只是转发va_list之类的。

所以我在汇编中实现了my_func:

; This function needs to be as compact as possible
my_func PROC
; assume 123 is the ID to be passed along with the arguments that my_func is called with
mov r10, 123 
jmp address_of_the_real_target_function
my_func

我只是跳转到目标函数,并在一个单独的寄存器中传递ID-在这种情况下为R10。

ARG* the_real_target_function(ARG* arg0, ...)
{
auto id = ReadRegister();
// ... do stuff ...
}

到目前为止,这一切都很好——唯一令人讨厌的是,我需要另一个汇编助手函数来读取正确的C++函数中的R10

ReadRegister PROC
mov rax, r10
ret
ReadRegister ENDP

这有点烦人,因为该调用不会内联。

因此,问题来了——有没有办法在C++中直接读取这个寄存器?

(否则,我可能会考虑使用SSE寄存器,它应该可以通过内部程序读取,但很好奇是否有办法只使用64位或32位寄存器)

感谢

--

edit:我相信这不是链接主题的重复。中列出的解决方案特定于其他编译器,或者在操作系统MSVC的情况下,仅限32位(x64上不支持内联程序集)

--

编辑2:关于我为什么要这么做的更多上下文。

这被认为是一个Excel插件(基本上,它将托管插件并向Excel公开其功能)。

为了在Excel中注册函数,我需要将其绑定到DLL导出的特定函数。我事先不知道需要注册和调用多少插件函数。因此,我需要实现大量导出的函数——数千个。足够总是为所有可用的插件提供注册槽。

为了控制DLL的整体大小,我需要注册的函数非常小,并且理想情况下还能够处理可变参数(因为我不知道编译时插件函数的形状;由于空间限制,我想避免为任何可能的任意参数创建回调)

更有趣的是,它需要在x64和x86中工作——尽管在后一种情况下,该函数是由Excel通过stdcall约定调用的,所以通常的C++可变参数不起作用。但是,至少在运行时,我可以找到传递给函数的参数的数量(和类型),所以我应该能够自己处理堆栈。

所以,最重要的是,我的想法是拥有这些纤细的蹦床函数,它将把所有参数及其ID转发给某个中央处理器(如上面X64中所述;以及X86中的堆栈)。

然后,处理程序将事情稍微整理一下,即为参数创建一些标准化的迭代器,调用通过该ID等注册的实际插件函数。

static thread_local变量需要很少的指令,所以它并不像您想要的那么瘦。然而,它将是完全可移植的。

有一种便携性较低但教学效率较高的方法。注意TEB中的任意数据槽。因此,x86上的__readfsdword(0x14)/__writefsdword(0x14)和x64上的__readgsqword(0x28)/__writegsqword(0x28)可以做到这一点。如果没有其他人将同样的额外空间用于其他目的。