将 gcc 内联汇编转换为 ml64

标签 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 内联汇编。另一个是我认为我将能够像调用任何其他 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.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

关于将 gcc 内联汇编转换为 ml64,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45602107/

相关文章:

linux - ARM 上未对齐内存访问的函数

c++ - 是否存在任何情况下有效的 C 代码无法使用 g++ 正确编译

linux - 为什么这个简单的汇编程序适用于 AT&T 语法而不是 Intel 语法?

c - 了解 getpid() 系统调用的 strace

c - SIMD 将 12 位字段解包为 16 位

C stdio 重定向到子进程或从子进程重定向

c - 如何在指针中保存多种类型的数据

assembly - pcasm书籍示例

linux - 如何在 x86 linux 上执行 MIPS 汇编程序?

c - gtk 复合小部件焦点