作为尝试为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内联汇编。另一个是我认为我可以像任何其他msvc_windows_amd64_threadentry
函数一样调用extern
,但我不完全确定。老实说,我从来没有过多处理过装配,所以我以前从未遇到过这些问题。
答案 0 :(得分:2)
您根本不需要使用程序集将此代码移植到Microsoft C ++。您可以使用__writegsqword
内在函数替换第一个汇编指令,然后使用plain 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