我有这段代码
__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 的列表。如果您想了解更多信息。 MSVC 和 GCC 差别很大。 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/