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位寄存器来做到这一点)
谢谢
-
编辑:我相信这不是链接主题的重复。其中列出的解决方案特定于其他编译器,或者仅适用于os MSVC(仅32位)(x64不支持内联汇编)
-
编辑2:有关我为什么要这样做的更多背景信息。
这实际上是一个Excel插件(基本上将用于托管插件并将其功能公开给Excel)。
为了在Excel中注册功能,我需要将其绑定到由DLL导出的特定功能。我事先不知道(=在编译时)需要注册多少个或调用什么插件函数。 因此,我需要实现大量导出功能。始终具有所有可用插件的注册位。
为了控制DLL的整体大小,我需要注册的函数非常纤细,并且理想情况下还应该能够处理可变参数args(因为我不知道插件函数的形状如何)编译时;由于空间限制,我想避免为任何可能的参数怪异创建回调)
为了获得更多乐趣,它需要在x64和x86中工作-尽管在后一种情况下,该函数是由Excel通过stdcall约定调用的,因此通常的C ++可变参数无法使用。但是,至少在运行时,我可以找到传递给函数的args的数量(和类型),因此我应该能够自己处理堆栈。
所以,最重要的是,我的想法是拥有这些苗条的蹦床函数,这些函数会将所有参数及其ID转发给某个中央处理程序(如X64中所述;并通过X86中的堆栈)。
然后处理程序将事情弄得井井有条-即为参数创建一些标准化的迭代器,调用通过该ID注册的实际插件函数,等等。
答案 0 :(得分:1)
static thread_local
变量将只需要很少的指令,因此它并不是您想要的那么苗条。
但是它将完全可移植。
可移植性较低,但指令效率更高。
注意TEB中的任意数据槽。
因此,x86上的__readfsdword(0x14)
/ __writefsdword(0x14)
和x64上的__readgsqword(0x28)
/ __writegsqword(0x28)
可以解决这个问题。如果没有其他人将相同的额外空间用于其他目的。