Visual studio 如何使用Visual C+插入重复的NOP语句+';s内联汇编程序? VisualC++,使用微软的编译器,允许我们使用:定义内联汇编代码 __asm { nop }

Visual studio 如何使用Visual C+插入重复的NOP语句+';s内联汇编程序? VisualC++,使用微软的编译器,允许我们使用:定义内联汇编代码 __asm { nop },visual-studio,assembly,x86,inline-assembly,cl,Visual Studio,Assembly,X86,Inline Assembly,Cl,我需要的是一个宏,它可以将这样的指令乘以n倍,如: ASM_EMIT_MULT(op, times) 例如: ASM_EMIT_MULT(0x90, 160) 可能吗?我怎样才能做到这一点呢?使用MASM,这是非常简单的。安装的一部分是一个名为listing.inc的文件(因为现在每个人都将MASM作为Visual Studio的一部分,所以它将位于Visual Studio根目录/VC/include中)。此文件定义了一系列npad宏,这些宏采用单个size参数,并扩展到一个适当的非破坏性

我需要的是一个宏,它可以将这样的指令乘以n倍,如:

ASM_EMIT_MULT(op, times)
例如:

ASM_EMIT_MULT(0x90, 160)

可能吗?我怎样才能做到这一点呢?

使用MASM,这是非常简单的。安装的一部分是一个名为
listing.inc
的文件(因为现在每个人都将MASM作为Visual Studio的一部分,所以它将位于Visual Studio根目录/VC/include中)。此文件定义了一系列
npad
宏,这些宏采用单个
size
参数,并扩展到一个适当的非破坏性“填充”操作码序列。如果只需要一个字节的填充,则使用明显的
nop
指令。但英特尔实际上建议,在达到所需长度之前,不要使用一长串的
nop
s。这些预定义的
npad
宏使您无需记忆该表,更不用说使代码更具可读性了

不幸的是,内联汇编不是一个功能齐全的汇编程序。在像MASM这样的实际汇编程序中,您可能会发现缺少很多东西。宏()和重复()是缺少的内容之一

然而。使用它非常简单。下面是一个非常愚蠢的例子,我用随机
align
s添加了工作代码:

unsigned long CountDigits(unsigned long value)
{
__asm
{
mov edx,DWORD PTR[值]
bsr eax,edx
对齐4
xor eax,1073741792
mov eax,DWORD PTR[4*eax+kMaxDigits+132]
对齐16
cmp edx,DWORD PTR[4*eax+kPowers-4]
sbb eax,0
对齐8
}
}
这将生成以下输出(MSVC的程序集列表使用
npad x
,其中
x
是字节数,就像您在MASM中编写它一样):

公共数字
_文本段
_价值$=8
计数数字程序
000008B 54 24 04 mov edx,DWORD PTR价值$[esp-4]
00004 0f bd c2 bsr eax,edx
00007 90 npad 1;//强制执行“对齐4”
00008 35 e0 ff ff 3f异或eax,1073741792
0000d 8b 04 85 84 00
00 mov eax,DWORD PTR_kMaxDigits[eax*4+132]
00014 eb 0a 8d a4 24
00008D
4900新台币12;//执行“对齐16”
00020 3b 14 85 fc ff
ff cmp edx,DWORD PTR_kPowers[eax*4-4]
00027 83 d8 00 sbb eax,0
0002a 8d 9b 00 00
00 npad 6;//强制执行“对齐8”
00030 c2 04 00 ret 4
CountDigits ENDP
_文本结尾

如果您实际上不想强制对齐,而只是想插入任意数量的
nop
s(可能作为以后热修补的填充物),那么您可以使用C宏来模拟效果:

#定义NOP1 uu asm{nop}
#定义nop2nop1nop1
#定义NOP4 NOP2 NOP2
#定义NOP8 NOP4 NOP4
#定义NOP16 NOP8 NOP8
// ...
#定义NOP64 NOP16 NOP16 NOP16 NOP16
//……等等。
然后根据需要添加代码:

unsigned long CountDigits(unsigned long value)
{
__asm
{
mov edx,DWORD PTR[值]
bsr eax,edx
NOP8
xor eax,1073741792
mov eax,DWORD PTR[4*eax+kMaxDigits+132]
NOP4
cmp edx,DWORD PTR[4*eax+kPowers-4]
sbb eax,0
}
}
要生成以下输出:

公共数字
_文本段
_价值$=8
计数数字程序
000008B 54 24 04 mov edx,DWORD PTR价值$[esp-4]
00004 0f bd c2 bsr eax,edx
00007 90 npad 1;//当然,这些都是很好的老一套
00008 90NPAD 1
00009 90 npad 1
0000a 90 npad 1
0000b 90 npad 1
0000c 90 npad 1
0000d 90 npad 1
0000e 90 npad 1
0000f 35 e0 ff ff 3f异或eax,1073741792
00014 8b 04 85 84 00
00 mov eax,DWORD PTR_kMaxDigits[eax*4+132]
0001b 90 npad 1
0001c 90 npad 1
0001d 90 npad 1
0001e 90 npad 1
0001f 3b 14 85 fc ff
ff cmp edx,DWORD PTR_kPowers[eax*4-4]
00026 83 d8 00 sbb eax,0
00029 c2 04 00 ret 4
CountDigits ENDP
_文本结尾

或者,更酷的是,我们可以使用一点模板元编程魔术来获得同样的风格效果。只需定义以下模板函数及其专门化(对于防止无限递归很重要):

模板uu forceinline void npad()
{
npad();
__asm{nop}
}
模板uu forceinline void npad(){}
然后像这样使用它:

unsigned long CountDigits(unsigned long value)
{
__asm
{
mov edx,DWORD PTR[值]
bsr eax,edx
}
npad();
__asm
{
xor eax,1073741792
mov eax,DWORD PTR[4*eax+kMaxDigits+132]
}
npad();
__asm
{
cmp edx,DWORD PTR[4*eax+kPowers-4]
sbb eax,0
}
}

这将在所有优化的构建中生成所需的输出(与上面的输出完全相同),无论您是针对大小(
/O1
)还是速度(
/O2
)-…进行优化,但在调试构建中不会。如果在调试版本中需要它,则必须使用C宏:-(

使用MASM,这非常简单。安装的一部分是一个名为
listing.inc
的文件(因为现在每个人都将MASM作为Visual Studio的一部分,它将位于Visual Studio根目录/VC/include中)。该文件定义了一系列采用单个
大小的
npad
template <size_t N> __forceinline void npad()
{
    npad<N-1>();
    __asm  { nop }
}
template <> __forceinline void npad<0>()  { }