将VS转换为GCC内联汇编

时间:2016-06-07 19:14:47

标签: visual-studio gcc x86 porting inline-assembly

我有这段代码

__asm
{
    mov eax, fs:[18h]
    mov eax, [eax + 30h]
    mov eax, [eax + 0Ch]
    mov pmInfo, eax
}

这应该在第一行中检索TEB,在第二行中检索PEB,最后一行是包含过程模块信息的结构。

typedef struct _ProcessModuleInfo
{
    unsigned int size;
    unsigned int initialized;
    HANDLE SsHandle;
    LIST_ENTRY LoadOrder;
    LIST_ENTRY InitOrder;
    LIST_ENTRY MemoryOrder;
} ProcessModuleInfo, *pProcessModuleInfo;

我的问题是,如何将这个程序集转换为codeblocks的GCC编译器?我真的很无能为力......

1 个答案:

答案 0 :(得分:2)

您可以在 GCC 文档中了解有关GCC assembler templates的更多信息。如果您想了解更多信息,Peter Cordes有一个Stackoverflow答案,其中包含inline assembler列表。 MSVC GCC 差别很大。 GCC 不知道模板的作用或指令的执行情况。 GCC 取而代之的是基于constraints - 输入,输出和clobber的列表进行替换。

GCC 扩展汇编程序模板,它与 MSVC 内联汇编程序非常接近,可能如下所示:

__asm__ (
    "mov %%fs:0x18, %0\n\t"
    "mov 0x30(%0), %0\n\t"
    "mov 0x0C(%0), %0\n\t"
    : "=r"(pmInfo));

在您的情况下,您需要一个寄存器用于内部使用。它不需要是 EAX ,但可以是 GCC 可用的任何寄存器。我们使用"=r"输出约束,表示我们希望 GCC 选择一个可用的寄存器。我们通过汇编程序模板中的%0引用第一个(在这种情况下是唯一的)约束。关于约束的"=r"(pmInfo)表示当模板中的指令完成时,所选寄存器中的值将被放入pmInfo

GCC 扩展汇编程序是一个棘手的工作,很容易出错。使用返回指向ProcessModuleInfo结构的指针的函数创建汇编程序文件可能会更好。这样就无需理解 GCC 的扩展汇编程序模板,并处理其错综复杂的模板。

Stackoverflow用户DavidWohlferd写了GCC wiki article,说明为什么使用 GCC 内联汇编程序应该避免如果可能。

如果%0看起来有点令人困惑,可以为每个输入和输出操作数指定一个符号名称,而不是%和模板中的数字。代码看起来像这样:

__asm__ (
    "mov %%fs:0x18, %[tempreg]\n\t"
    "mov 0x30(%[tempreg]), %[tempreg]\n\t"
    "mov 0x0C(%[tempreg]), %[tempreg]\n\t"
    : [tempreg]"=r"(pmInfo));

方括号中的[tempreg]为操作数提供了一个名称,作为使用序数位置的替代方法。这样也可以更容易地阅读模板。