将gcc内联汇编转换为ml64

时间:2017-08-09 23:23:42

标签: c gcc assembly visual-c++

作为尝试为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,但我不完全确定。老实说,我从来没有过多处理过装配,所以我以前从未遇到过这些问题。

1 个答案:

答案 0 :(得分:2)

您根本不需要使用程序集将此代码移植到Microsoft C ++。您可以使用__writegsqword内在函数替换第一个汇编指令,然后使用plain C替换最后两个汇编指令。例如:

__writegsqword(0x28, (unsigned long long) ts.tls);
*(void **)ts.tls = (void *) ts.g;

请注意,根据ts.tlsts.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