将 VS 转换为 GCC 内联汇编
Converting VS to GCC 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 编译器?
您可以详细了解 GCC assembler templates in the GCC documentation. Peter Cordes has a Whosebug answer with a list of if you wish to learn more. MSVC and GCC differ greatly. GCC has no knowledge of what a template does or the instructions executes. GCC instead does substitutions based upon a list of constraints - 输入、输出和破坏。
一个 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 扩展汇编程序使用起来很棘手,而且很容易出错。您最好创建一个汇编程序文件,其中包含 returns 指向 ProcessModuleInfo 结构的指针的函数。这消除了理解 GCC 的扩展汇编器模板和处理其复杂性的需要。
Whosebug 用户 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]
为操作数提供了一个名称,作为使用序数位置的替代方法。这也让阅读模板变得更容易一些。
我有这段代码
__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 编译器?
您可以详细了解 GCC assembler templates in the GCC documentation. Peter Cordes has a Whosebug answer with a list of
一个 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 扩展汇编程序使用起来很棘手,而且很容易出错。您最好创建一个汇编程序文件,其中包含 returns 指向 ProcessModuleInfo 结构的指针的函数。这消除了理解 GCC 的扩展汇编器模板和处理其复杂性的需要。
Whosebug 用户 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]
为操作数提供了一个名称,作为使用序数位置的替代方法。这也让阅读模板变得更容易一些。