visual-studio - 将 VS 转换为 GCC 内联汇编

标签 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;

我的问题是,如何将该程序集转换为代码块的 GCC 编译器?

最佳答案

您可以了解更多关于GCC assembler templates的信息在GCC文档中。 Peter Cordes 在 Stackoverflow 上有一个答案,其中包含 inline assembler 的列表。如果您想了解更多信息。 MSVCGCC 差别很大。 GCC 不知道模板的作用或指令的执行情况。 GCC 相反,根据 constraints 列表进行替换- 输入、输出和破坏。

一个非常接近 MSVC 内联汇编器的 GCC 扩展汇编器模板可能如下所示:

__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]为操作数提供了一个名称,作为使用序数位置的替代方法。这也使得阅读模板变得更加容易。

关于visual-studio - 将 VS 转换为 GCC 内联汇编,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37687532/

相关文章:

c# - 在 Windows 窗体中使用线程

visual-studio - "stdafx.h"在 Visual Studio 中有何用途?

c - 使用 gcc 理解共享库

c - 为什么 GCC -mcmodel=large 在没有 -fPIC 的情况下即使使用 -no-pie 标志也会向函数调用添加偏移量?

linux - Linux 上 32 位代码中的 "int 0x80"或 "syscall"哪个更好?

optimization - 汇编中高数的划分

c# - 如何关闭未使用的用途变灰?

visual-studio - 在网站和 Cordova 项目之间共享文件

c - gcc arm __asm inline 在参数中传递常量

assembly - 哪个 x86 寄存器表示 movsb 指令中的源位置?