Avec MASM, c'est très simple à faire. Une partie de l'installation est un fichier nommé listing.inc
(puisque tout le monde obtient MASM dans le cadre de Visual Studio maintenant, cela sera situé dans votre répertoire racine Visual Studio/VC/include). Ce fichier définit une série de macros npad
qui prennent un seul argument size
et développent une séquence appropriée d'opcodes de "remplissage" non destructifs. Si vous n'avez besoin que d'un octet de remplissage, vous utilisez l'instruction nop
. Mais plutôt que d'utiliser une longue série de nop
jusqu'à ce que vous atteigniez la longueur désirée, Intel recommande effectivement other non-destructive opcodes of the appropriate length, tout comme other vendors. Ces macros pré-définies npad
vous libèrent de devoir mémoriser cette table, sans parler de rendre le code beaucoup plus lisible.
Malheureusement, l'assemblage en ligne n'est pas un assembleur complet. Il y a beaucoup de choses manquantes que vous attendez de trouver dans de vrais assembleurs comme MASM. Macros (MACRO
) et les répétitions (REPEAT
/REPT
) sont parmi les choses qui manquent. Cependant, ALIGN
directivesare available in inline assembly. These will generate the required number of nop
s or other non-destructive opcodes to enforce alignment of the next instruction. L'utilisation de ceci est simple. Voici un exemple très stupide, où j'ai pris le code de travail et poivré avec align
aléatoires s:
unsigned long CountDigits(unsigned long value)
{
__asm
{
mov edx, DWORD PTR [value]
bsr eax, edx
align 4
xor eax, 1073741792
mov eax, DWORD PTR [4 * eax + kMaxDigits+132]
align 16
cmp edx, DWORD PTR [4 * eax + kPowers-4]
sbb eax, 0
align 8
}
}
Cela génère la sortie suivante (les listes de montage de MSVC utilisent npad x
, où x
est le nombre d'octets, juste comme vous écririez dans MASM):
PUBLIC CountDigits
_TEXT SEGMENT
_value$ = 8
CountDigits PROC
00000 8b 54 24 04 mov edx, DWORD PTR _value$[esp-4]
00004 0f bd c2 bsr eax, edx
00007 90 npad 1 ;// enforcing the "align 4"
00008 35 e0 ff ff 3f xor eax, 1073741792
0000d 8b 04 85 84 00
00 00 mov eax, DWORD PTR _kMaxDigits[eax*4+132]
00014 eb 0a 8d a4 24
00 00 00 00 8d
49 00 npad 12 ;// enforcing the "align 16"
00020 3b 14 85 fc ff
ff ff cmp edx, DWORD PTR _kPowers[eax*4-4]
00027 83 d8 00 sbb eax, 0
0002a 8d 9b 00 00 00
00 npad 6 ;// enforcing the "align 8"
00030 c2 04 00 ret 4
CountDigits ENDP
_TEXT ENDS
Si vous n'êtes pas vouloir réellement faire respecter l'alignement, mais juste à insérer un nombre arbitraire de nop
s (peut-être en tant que charge pour plus tard chaud patc ? Hing), vous pouvez utiliser des macros C pour simuler l'effet:
#define NOP1 __asm { nop }
#define NOP2 NOP1 NOP1
#define NOP4 NOP2 NOP2
#define NOP8 NOP4 NOP4
#define NOP16 NOP8 NOP8
// ...
#define NOP64 NOP16 NOP16 NOP16 NOP16
// ...etc.
Et puis poivrer votre code comme vous le souhaitez:
unsigned long CountDigits(unsigned long value)
{
__asm
{
mov edx, DWORD PTR [value]
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
}
}
pour produire la sortie suivante:
PUBLIC CountDigits
_TEXT SEGMENT
_value$ = 8
CountDigits PROC
00000 8b 54 24 04 mov edx, DWORD PTR _value$[esp-4]
00004 0f bd c2 bsr eax, edx
00007 90 npad 1 ;// these are, of course, just good old NOPs
00008 90 npad 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 xor eax, 1073741792
00014 8b 04 85 84 00
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 ff cmp edx, DWORD PTR _kPowers[eax*4-4]
00026 83 d8 00 sbb eax, 0
00029 c2 04 00 ret 4
CountDigits ENDP
_TEXT ENDS
Ou, encore plus cool, nous pouvons utiliser un peu de magie de méta-programmation de modèle pour obtenir le même effet dans style.Il suffit de définir la fonction de modèle suivant et sa spécialisation (important pour éviter une récursion infinie):
template <size_t N> __forceinline void npad()
{
npad<N-1>();
__asm { nop }
}
template <> __forceinline void npad<0>() { }
Et l'utiliser comme ceci:
unsigned long CountDigits(unsigned long value)
{
__asm
{
mov edx, DWORD PTR [value]
bsr eax, edx
}
npad<8>();
__asm
{
xor eax, 1073741792
mov eax, DWORD PTR [4 * eax + kMaxDigits+132]
}
npad<4>();
__asm
{
cmp edx, DWORD PTR [4 * eax + kPowers-4]
sbb eax, 0
}
}
qui va produire la sortie désirée (exactement le même que le un juste au-dessus) dans toutes les versions optimisées - que vous optimisiez pour la taille (/O1
) ou la vitesse (/O2
) - & hellip; mais pas dans les versions de débogage. Si vous en avez besoin dans les versions de débogage, vous devrez utiliser les macros C. :-(
https://msdn.microsoft.com/en-us/library/kyzds0ks.aspx, https://msdn.microsoft.com/en-us/library/352sth8z.aspx –
@ JoseManuelAbarcaRodríguez merci pour les liens, mais ces références ne font pas clair comment puis-je résoudre le problème –