作为尝试为 cgo 实现 msvc 支持的一部分,我发现我需要将一些内联 gcc 程序集移植到 ml64。这是原始程序集:
ts = *(ThreadStart*)v;
/*
* Set specific keys in thread local storage.
*/
__asm {
"movq %0, %%gs:0x28\n" // MOVL tls0, 0x28(GS)
"movq %%gs:0x28, %%rax\n" // MOVQ 0x28(GS), tmp
"movq %1, 0(%%rax)\n" // MOVQ g, 0(GS)
:: "r"(ts.tls), "r"(ts.g) : "%rax"
}
这是我创建的外部汇编文件:
PUBLIC msvc_windows_amd64_threadentry
.CODE
msvc_windows_amd64_threadentry PROC
MOV gs:[0x28], ts.tls
MOV rax, gs:[0x28]
MOV gs:[0], ts.g
ret
msvc_windows_amd64_threadentry ENDP
END
显然存在一些问题。一方面,我现在不知道如何让汇编器知道ts
的结构; gcc 显然知道它,因为它在正在编译的文件中,但 msvc 不支持 amd64 内联汇编。另一个是我认为我将能够像调用任何其他 extern
函数一样调用 msvc_windows_amd64_threadentry
,但我不完全确定。老实说,我从来不需要处理太多的 assembly 问题,所以我以前从来没有遇到过这些问题。
最佳答案
您根本不需要使用汇编将此代码移植到 Microsoft C++。您可以使用 __writegsqword
intrinsic 替换第一条汇编指令,然后使用普通 C 替换最后两条汇编指令。例如:
__writegsqword(0x28, (unsigned long long) ts.tls);
*(void **)ts.tls = (void *) ts.g;
请注意,根据 ts.tls
和 ts.g
的类型,使用不同的类型转换可能会更好,或者完全避免使用它们。
通过添加如下函数,您可以将相同的代码与 GCC 和 Microsoft C++ 一起使用:
#ifdef __GNUC__
static inline void
__writegsqword(unsigned long long offset, unsigned long long value) {
asm("movq %0,%%gs:%1" :: "re" (value), "m" (*(int *)offset));
}
#endif
关于将 gcc 内联汇编转换为 ml64,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45602107/