在 x64 中内联汇编函数 Visual Studio
Making assembly function inline in x64 Visual Studio
我知道 x64 模式下的 MSVC 编译器不支持内联汇编代码片段,为了使用汇编代码,您必须像这样在某些外部 my_asm_funcs.asm 文件中定义您的函数:
my_asm_func PROC
mov rax, rcx
ret
my_asm_func ENDP
然后在您的 .c 或 .h 文件中为函数定义一个 header:
int my_asm_func(int x);
尽管该解决方案解决了很多问题,但我仍然有兴趣使该汇编代码函数成为内联的,换句话说 - 编译后我不想要任何 "calls" 到 my_asm_func,我只是想让这段程序集粘到我最终编译的代码中。我尝试使用 inline 和 __forceinline 关键字声明该函数,但似乎没有任何帮助。还有办法做我想做的事吗?
不行,没有办法如你所愿
如您所说,Microsoft 的编译器不支持 x86-64 目标的内联汇编。这迫使您在外部代码模块 (*.asm) 中定义您的汇编函数,assemble 它们与 MASM,并且 link 结果连同您单独编译的 C/C++ 代码.
所需的步骤分离意味着 C/C++ 编译器无法内联您的汇编函数,因为它们在编译时对它不可见。
即使启用 link 时间代码生成 (LTCG),您的汇编模块也不会内联,因为 linker 根本不支持这个。
绝对没有办法让编写在单独模块中的汇编函数直接内联到 C 或 C++ 代码中。
inline
或 __forceinline
关键字不可能有任何作用。事实上,如果没有编译器错误(或至少是警告),您无法使用它们。这些注释必须在函数的 definition 上进行(对于内联函数,它与其声明相同),但不能将其放在函数的定义上,因为它已定义在一个单独的 *.asm 文件中。这些不是 MASM 关键字,因此尝试将它们添加到定义中必然会导致错误。将它们放在 C 头文件中汇编函数的前向声明中同样不会成功,因为那里没有要内联的代码——只有一个原型。
这就是为什么 Microsoft 推荐使用 intrinsics. 你可以直接在你的 C 或 C++ 代码中使用它们,编译器会发出自动生成相应的汇编代码。这不仅实现了所需的内联,而且内在函数甚至允许优化器运行,从而进一步改进结果。不,内在函数不会产生完美的代码,也不是所有的内在函数都适用,但这是使用 Microsoft 编译器所能做的最好的事情。
您唯一的其他选择是坐下来玩弄 C/C++ 代码的各种排列,直到您让编译器生成所需的目标代码。在您希望生成的指令无法使用内在函数的情况下,这可能非常强大,但它确实需要花费大量时间来坐立不安,并且您必须重新访问它以确保它继续执行您的操作升级编译器版本时需要。
由于标题提到 Visual Studio 而不是 MSVC,我建议通过 Visual Studio 安装程序安装 Clang。它可以像 MSVC 一样使用,无需配置自定义构建任务或任何东西,它支持使用 Intel 语法和变量作为操作数的内联汇编。
只需 select "LLVM (clang-cl)" in Platform Toolset
来自项目 属性 页面的 General
部分,你就可以开始了。
是的,你可以。 Assemble 您的程序作为 shellcode 并提取字节,然后将其包含在代码中具有 RWX 内存保护的缓冲区中。调用代码。
我知道 x64 模式下的 MSVC 编译器不支持内联汇编代码片段,为了使用汇编代码,您必须像这样在某些外部 my_asm_funcs.asm 文件中定义您的函数:
my_asm_func PROC
mov rax, rcx
ret
my_asm_func ENDP
然后在您的 .c 或 .h 文件中为函数定义一个 header:
int my_asm_func(int x);
尽管该解决方案解决了很多问题,但我仍然有兴趣使该汇编代码函数成为内联的,换句话说 - 编译后我不想要任何 "calls" 到 my_asm_func,我只是想让这段程序集粘到我最终编译的代码中。我尝试使用 inline 和 __forceinline 关键字声明该函数,但似乎没有任何帮助。还有办法做我想做的事吗?
不行,没有办法如你所愿
如您所说,Microsoft 的编译器不支持 x86-64 目标的内联汇编。这迫使您在外部代码模块 (*.asm) 中定义您的汇编函数,assemble 它们与 MASM,并且 link 结果连同您单独编译的 C/C++ 代码.
所需的步骤分离意味着 C/C++ 编译器无法内联您的汇编函数,因为它们在编译时对它不可见。
即使启用 link 时间代码生成 (LTCG),您的汇编模块也不会内联,因为 linker 根本不支持这个。
绝对没有办法让编写在单独模块中的汇编函数直接内联到 C 或 C++ 代码中。
inline
或 __forceinline
关键字不可能有任何作用。事实上,如果没有编译器错误(或至少是警告),您无法使用它们。这些注释必须在函数的 definition 上进行(对于内联函数,它与其声明相同),但不能将其放在函数的定义上,因为它已定义在一个单独的 *.asm 文件中。这些不是 MASM 关键字,因此尝试将它们添加到定义中必然会导致错误。将它们放在 C 头文件中汇编函数的前向声明中同样不会成功,因为那里没有要内联的代码——只有一个原型。
这就是为什么 Microsoft 推荐使用 intrinsics. 你可以直接在你的 C 或 C++ 代码中使用它们,编译器会发出自动生成相应的汇编代码。这不仅实现了所需的内联,而且内在函数甚至允许优化器运行,从而进一步改进结果。不,内在函数不会产生完美的代码,也不是所有的内在函数都适用,但这是使用 Microsoft 编译器所能做的最好的事情。
您唯一的其他选择是坐下来玩弄 C/C++ 代码的各种排列,直到您让编译器生成所需的目标代码。在您希望生成的指令无法使用内在函数的情况下,这可能非常强大,但它确实需要花费大量时间来坐立不安,并且您必须重新访问它以确保它继续执行您的操作升级编译器版本时需要。
由于标题提到 Visual Studio 而不是 MSVC,我建议通过 Visual Studio 安装程序安装 Clang。它可以像 MSVC 一样使用,无需配置自定义构建任务或任何东西,它支持使用 Intel 语法和变量作为操作数的内联汇编。
只需 select "LLVM (clang-cl)" in Platform Toolset
来自项目 属性 页面的 General
部分,你就可以开始了。
是的,你可以。 Assemble 您的程序作为 shellcode 并提取字节,然后将其包含在代码中具有 RWX 内存保护的缓冲区中。调用代码。