如何编写跨平台(32和64位)垃圾汇编代码?

时间:2017-12-18 01:59:49

标签: c++ assembly

我需要编写一些(安全使用)随机垃圾汇编代码,以便对C ++项目进行一些混淆练习。 到目前为止,我只能找到这个:

#define JUNKCODE        \
__asm{push eax}            \
__asm{xor eax, eax}        \
__asm{setpo al}            \
__asm{push edx}            \
__asm{xor edx, eax}        \
__asm{sal edx, 2}        \
__asm{xchg eax, edx}    \
__asm{pop edx}            \
__asm{or eax, ecx}        \
__asm{pop eax}

对于64位项目,似乎没有在Xcode上编译

如何创建可以安全添加到我的项目的多个版本的垃圾组装代码,它是32-64位兼容和跨平台(Windows VS2013和Mac Xcode8)?

1 个答案:

答案 0 :(得分:1)

要编写将以任一模式汇编的asm,请使用32位操作数大小,并避免使用push / pop:它们在x86-64的32位操作数大小中不可用。只有模式的全宽寄存器大小和16位可用于推/弹。 (即机器代码中的the 0x66 operand-size prefix works, but REX.W=0 doesn't,因此push eax在64位模式下无法编码。)

如果您希望相同的机器代码在两种模式下都能工作,也请避免inc / dec(32位模式下的短编码在64位模式下成为REX前缀)。如果你只需要组装的asm源,那么inc / dec就可以了。

对于C ++中的inline asm:

避免修改任何内存或进行任何函数调用。这很难安全地做到这一点,所以如果你只想要垃圾代码,你可以只使用寄存器。您甚至无法在x86-64代码中安全地push使用System V ABI,因为编译器可能正在使用堆栈下方的红色区域and there's no way to tell it you want to clobber it。我不知道这是否适用于使用MSVC inline-asm语法而不是GNU语法的Clang,其中必须明确声明clobbers。

首选GNU C内联asm语法(使用适当的约束来告诉编译器你使用哪些寄存器)。

MSVC本身不支持64位模式下的任何内联asm语法。

Xcode(clang)确实支持MSVC的语法和GNU语法,即使在64位模式下它也可能支持MSVC语法。

MSVC样式的内联asm语法基本上用于包装短片段(输入必须通过内存反弹,因为没有语法要求寄存器中的输入)和reportedly has been unreliable from version to version in MS's compiler。 MS可能正在寻找理由或方法来放弃它,并且不支持x86-64是有意义的。如果它们保持不变,从内联asm访问函数args会更糟糕,因为它们不会在内存中启动。无论如何,MSVC inline asm语法已经半死,很好的解决。

无论如何,如果你真的想在32位MSVC中使用一些内联asm,那么一定要使用那种语法。 __asm __emit可以在64位MSVC I think IACA headers use that中执行某些操作,因此如果您只是希望代码看起来很奇怪,您可以手动编码一些NOP。