Note
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Cette rubrique décrit l’utilisation de la syntaxe d’expression MICROSOFT Macro Assembleur (MASM) avec les outils de débogage Windows.
Le débogueur accepte deux types d’expressions numériques différents : les expressions C++ et les expressions MASM. Chacune de ces expressions suit ses propres règles de syntaxe pour l’entrée et la sortie.
Pour plus d’informations sur l’utilisation de chaque type de syntaxe, consultez Évaluation des expressions et ? (Évaluer l’expression).
Dans cet exemple le ? la commande affiche la valeur du registre du pointeur d’instruction à l’aide de l’évaluateur d’expression MASM.
0:000> ? @rip
Evaluate expression: 140709230544752 = 00007ff9`6bb40770
Définir l’évaluateur d’expression sur MASM
Utilisez .expr (Choisir l’évaluateur d’expression) pour voir ce qu’est l’évaluateur d’expression par défaut et le remplacer par MASM.
0:000> .expr /s masm
Current expression evaluator: MASM - Microsoft Assembler expressions
Maintenant que l'évaluateur d'expressions par défaut a été modifié, la commande ? (Évaluer l’expression) peut être utilisée pour afficher des expressions MASM. Cet exemple additionne la valeur hexadécimale de 8 au registre rip.
0:000> ? @rip + 8
Evaluate expression: 140709230544760 = 00007ff9`6bb40778
La référence du registre @rip est décrite plus en détail dans la syntaxe de registre.
Nombres dans les expressions MASM du débogueur
Vous pouvez placer des nombres dans des expressions MASM en base 16, 10, 8 ou 2.
Utilisez la commande n (Définir la base de nombres) pour définir le radix par défaut sur 16, 10 ou 8. Tous les nombres non corrigés sont ensuite interprétés dans cette base. Vous pouvez remplacer le radix par défaut en spécifiant le préfixe 0x (hexadécimal), le préfixe 0n (décimal), le préfixe 0t (octal) ou le préfixe 0y (binaire).
Vous pouvez également spécifier des nombres hexadécimaux en ajoutant un h après le nombre. Vous pouvez utiliser des lettres majuscules ou minuscules dans des chiffres. Par exemple, « 0x4AB3 », « 0X4aB3 », « 4AB3h », « 4ab3h » et « 4aB3H » ont la même signification.
Si vous n’ajoutez pas de nombre après le préfixe d’une expression, le nombre est lu sous la forme 0. Par conséquent, vous pouvez écrire 0 en tant que 0, le préfixe suivi de 0 et uniquement le préfixe. Par exemple, en hexadécimal, « 0 », « 0x0 » et « 0x » ont la même signification.
Vous pouvez entrer des valeurs hexadécimales 64 bits au format xxxxxxxx’xxxxxxxx . Vous pouvez également omettre l’accent grave ('). Si vous incluez l’accent grave, l’extension de signe automatique est désactivée.
Cet exemple montre comment ajouter une valeur décimale, octale et binaire pour inscrire 10.
? @r10 + 0x10 + 0t10 + 0y10
Evaluate expression: 26 = 00000000`0000001a
Symboles dans les expressions MASM du débogueur
Dans les expressions MASM, la valeur numérique d’un symbole est son adresse mémoire. Selon ce que le symbole fait référence, cette adresse est l’adresse d’une variable globale, d’une variable locale, d’une fonction, d’un segment, d’un module ou d’une autre étiquette reconnue.
Pour spécifier le module auquel l’adresse est associée, incluez le nom du module et un point d’exclamation ( !) avant le nom du symbole. Si le symbole peut être interprété comme un nombre hexadécimal, incluez le nom du module et un point d’exclamation, ou simplement un point d’exclamation, avant le nom du symbole. Pour plus d’informations sur la reconnaissance des symboles, consultez Syntaxe des symboles et Correspondance des symboles.
Utilisez deux points-virgules ( ::) ou deux traits de soulignement (__) pour indiquer les membres d’une classe.
Utilisez un accent grave (') ou une apostrophe (') dans un nom de symbole uniquement si vous ajoutez un nom de module et un point d’exclamation avant le symbole.
Opérateurs numériques dans les expressions MASM
Vous pouvez modifier n’importe quel composant d’une expression à l’aide d’un opérateur unaire. Vous pouvez combiner deux composants à l’aide d’un opérateur binaire. Les opérateurs unaires sont prioritaires sur les opérateurs binaires. Lorsque vous utilisez plusieurs opérateurs binaires, les opérateurs suivent les règles de précédence fixe décrites dans les tableaux suivants.
Vous pouvez toujours utiliser des parenthèses pour remplacer les règles de précédence.
Si une partie d'une expression MASM est placée entre parenthèses et que deux arrobas (@@) se trouvent avant l'expression, l'expression est interprétée en fonction des règles d'expression C++. Vous ne pouvez pas ajouter d’espace entre les deux signes et la parenthèse ouvrante. Vous pouvez également spécifier l’évaluateur d’expression à l’aide de @@c++( ... ) ou de @@masm( ... ).
Lorsque vous effectuez des calculs arithmétiques, l’évaluateur d’expression MASM traite tous les nombres et symboles comme des types ULONG64.
Les opérateurs d’adresses unaires supposent que DS est le segment par défaut pour les adresses. Les expressions sont évaluées dans l’ordre de priorité de l’opérateur. Si les opérateurs adjacents ont une priorité égale, l’expression est évaluée de gauche à droite.
Vous pouvez utiliser les opérateurs unaires suivants.
| Opérateur | Sens |
|---|---|
+ |
Plus unaire |
- |
Unaire moins |
non |
Retourne 1 si l’argument est égal à zéro. Retourne zéro pour n’importe quel argument différent de zéro. |
Salut |
16 bits élevés |
faible |
Faible 16 bits |
par |
Octet de faible ordre depuis l’adresse spécifiée. |
$pby |
Même chose que by sauf qu'il utilise une adresse physique. Seule la mémoire physique qui utilise le comportement de mise en cache par défaut peut être lue. |
Wo |
Mot de faible ordre à partir de l’adresse spécifiée. |
$pwo |
Identique à wo , sauf qu’il prend une adresse physique. Seule la mémoire physique qui utilise le comportement de mise en cache par défaut peut être lue. |
dwo |
Double mot de l’adresse spécifiée. |
$pdwo |
Identique à dwo , sauf qu’il prend une adresse physique. Seule la mémoire physique qui utilise le comportement de mise en cache par défaut peut être lue. |
qwo |
Mot quadruple de l'adresse spécifiée. |
$pqwo |
Identique à qwo , sauf qu’il prend une adresse physique. Seule la mémoire physique qui utilise le comportement de mise en cache par défaut peut être lue. |
Poi |
Données à la taille du pointeur depuis l’adresse spécifiée. La taille du pointeur est de 32 bits ou 64 bits. Dans le débogage du noyau, cette taille est basée sur le processeur de l’ordinateur cible . Par conséquent, poi est le meilleur opérateur à utiliser si vous souhaitez des données de taille pointeur. |
$ppoi |
Identique à poi , sauf qu’il prend une adresse physique. Seule la mémoire physique qui utilise le comportement de mise en cache par défaut peut être lue. |
Exemples
L’exemple suivant montre comment utiliser poi pour déréférer un pointeur pour voir la valeur stockée à cet emplacement de mémoire.
Commencez par déterminer l’adresse de mémoire intéressante. Par exemple, nous pouvons examiner la structure de threads et décider de voir la valeur de CurrentLocale.
0:000> dx @$teb
@$teb : 0x8eed57b000 [Type: _TEB *]
[+0x000] NtTib [Type: _NT_TIB]
[+0x038] EnvironmentPointer : 0x0 [Type: void *]
[+0x040] ClientId [Type: _CLIENT_ID]
[+0x050] ActiveRpcHandle : 0x0 [Type: void *]
[+0x058] ThreadLocalStoragePointer : 0x1f8f9d634a0 [Type: void *]
[+0x060] ProcessEnvironmentBlock : 0x8eed57a000 [Type: _PEB *]
[+0x068] LastErrorValue : 0x0 [Type: unsigned long]
[+0x06c] CountOfOwnedCriticalSections : 0x0 [Type: unsigned long]
[+0x070] CsrClientThread : 0x0 [Type: void *]
[+0x078] Win32ThreadInfo : 0x0 [Type: void *]
[+0x080] User32Reserved [Type: unsigned long [26]]
[+0x0e8] UserReserved [Type: unsigned long [5]]
[+0x100] WOW32Reserved : 0x0 [Type: void *]
[+0x108] CurrentLocale : 0x409 [Type: unsigned long]
CurrentLocale se trouve 0x108 au-delà du début du TEB.
0:000> ? @$teb + 0x108
Evaluate expression: 613867303176 = 0000008e`ed57b108
Utilisez poi pour déréférencer cette adresse.
0:000> ? poi(0000008e`ed57b108)
Evaluate expression: 1033 = 00000000`00000409
La valeur retournée de 409 correspond à la valeur de CurrentLocale dans la structure TEB.
Vous pouvez également utiliser poi et des parenthèses pour déréférencer l’adresse calculée.
0:000> ? poi(@$teb + 0x108)
Evaluate expression: 1033 = 00000000`00000409
Utilisez les opérateurs unaires by ou wo pour renvoyer un octet ou un word à partir de l’adresse cible.
0:000> ? by(0000008e`ed57b108)
Evaluate expression: 9 = 00000000`00000009
0:000> ? wo(0000008e`ed57b108)
Evaluate expression: 1033 = 00000000`00000409
Opérateurs binaires
Vous pouvez utiliser les opérateurs binaires suivants. Les opérateurs de chaque cellule sont prioritaires sur ceux des cellules inférieures. Les opérateurs de la même cellule sont de la même priorité et sont analysés de gauche à droite.
| Opérateur | Sens |
|---|---|
* / mod (ou %) |
Multiplication Division d'entier Modulo (reste) |
+ - |
Ajout Soustraction |
<< >> >>> |
Décalage à gauche Décalage logique vers la droite Décalage droit arithmétique |
= (ou ==) < > <= >= != |
Égal à Inférieur à Supérieur à Inférieur ou égal à Supérieur ou égal à Non égal à |
et (ou &) |
AND au niveau du bit |
xor (ou ^) |
XOR au niveau du bit (OR exclusif) |
ou (ou |) |
OR au niveau du bit |
Les <opérateurs de comparaison , = >, == et != sont évalués à 1 si l’expression a la valeur true ou zéro si l’expression a la valeur false. Un seul signe égal (=) est identique à un signe égal double (==). Vous ne pouvez pas utiliser d’effets secondaires ou d’affectations dans une expression MASM.
Une opération non valide (telle qu'une division par zéro) entraîne une « erreur d’opérande » qui est retournée à la fenêtre Commande du débogueur.
Nous pouvons vérifier que la valeur retournée correspond 0x409 à l’aide de l’opérateur de comparaison ==.
0:000> ? poi(@$teb + 0x108)==0x409
Evaluate expression: 1 = 00000000`00000001
Opérateurs non numériques dans les expressions MASM
Vous pouvez également utiliser les opérateurs supplémentaires suivants dans les expressions MASM.
| Opérateur | Sens |
|---|---|
$fnsucc(FnAddress, RetVal, Flag) |
Interprète la valeur RetVal comme valeur de retour pour la fonction située à l’adresse FnAddress . Si cette valeur de retour est qualifiée de code de réussite, $fnsucc retourne TRUE. Sinon, $fnsucc retourne FALSE. Si le type de retour est BOOL, bool, HANDLE, HRESULT ou NTSTATUS, $fnsucc comprend correctement si la valeur de retour spécifiée est qualifiée de code de réussite. Si le type de retour est un pointeur, toutes les valeurs autres que NULL sont qualifiées de codes de réussite. Pour tout autre type, la réussite est définie par la valeur de Flag. Si l’indicateur est 0, une valeur différente de zéro de RetVal indique un succès. Si l’indicateur est égal à 1, une valeur de RetVal de zéro indique un succès. |
$iment (Adresse) |
Retourne l’adresse du point d’entrée d’image dans la liste des modules chargés. L’adresse spécifie l'adresse de base de l'image Portable Executable (PE). L'entrée est identifiée en recherchant le point d'entrée de l'image dans l'en-tête du fichier image PE spécifié par Adresse. Vous pouvez utiliser cette fonction pour les deux modules qui se trouvent déjà dans la liste des modules et pour définir des points d’arrêt non résolus à l’aide de la commande bu . |
$scmp(« String1 », « String2 ») |
Prend la valeur -1, 0 ou 1, comme le strcmp en utilisant la fonction C strcmp. |
$sicmp(« String1 », « String2 ») |
Prend la valeur -1, 0 ou 1, comme la fonction stricmp Microsoft Win32 . |
$spat(« String », « Pattern ») |
Prend la valeur TRUE ou FALSE selon que la chaîne correspond au modèle. La correspondance est insensible à la casse. Le modèle peut contenir divers caractères génériques et spécificateurs. Pour plus d’informations sur la syntaxe, consultez Syntaxe générique de chaîne. |
$vvalid(Adresse,Longueur) |
Détermine si la plage de mémoire qui commence à l’adresse et s’étend pour les octets de longueur est valide. Si la mémoire est valide, $vvalid prend la valeur 1. Si la mémoire n’est pas valide, $vvalid prend la valeur 0. |
Exemples
L’exemple suivant montre comment examiner la plage de mémoire valide autour d’un module chargé
Commencez par déterminer l’adresse de la zone d’intérêt, par exemple à l’aide de la commande lm (commande List Loaded Modules ).
0:000> lm
start end module name
00007ff6`0f620000 00007ff6`0f658000 notepad (deferred)
00007ff9`591d0000 00007ff9`5946a000 COMCTL32 (deferred)
...
Utilisez $vvalid pour vérifier une plage de mémoire.
0:000> ? $vvalid(0x00007ff60f620000, 0xFFFF)
Evaluate expression: 1 = 00000000`00000001
Utilisez $vvalid pour confirmer que cette plage plus grande est une plage de mémoire non valide.
0:000> ? $vvalid(0x00007ff60f620000, 0xFFFFF)
Evaluate expression: 0 = 00000000`00000000
Il s’agit également d’une plage non valide.
0:000> ? $vvalid(0x0, 0xF)
Evaluate expression: 0 = 00000000`00000000
N’utilisez pas pour retourner zéro lorsque la plage de mémoire est valide.
0:000> ? not($vvalid(0x00007ff60f620000, 0xFFFF))
Evaluate expression: 0 = 00000000`00000000
Utilisez $imnet pour examiner le point d'entrée de COMCTL32, dont nous avions précédemment déterminé l'adresse en utilisant la commande lm. Il commence à 00007ff9'591d0000.
0:000> ? $iment(00007ff9`591d0000)
Evaluate expression: 140708919287424 = 00007ff9`59269e80
Désassemblez l’adresse retournée pour examiner le code de point d’entrée.
0:000> u 00007ff9`59269e80
COMCTL32!DllMainCRTStartup:
00007ff9`59269e80 48895c2408 mov qword ptr [rsp+8],rbx
00007ff9`59269e85 4889742410 mov qword ptr [rsp+10h],rsi
00007ff9`59269e8a 57 push rdi
COMCTL32 s’affiche dans la sortie confirmant qu’il s’agit du point d’entrée de ce module.
Registres et Pseudo-Registers dans les expressions MASM
Vous pouvez utiliser des registres et des pseudo-registres dans des expressions MASM. Vous pouvez ajouter une arobase (@) avant tous les registres et pseudo-registres. Le signe at (@) permet au débogueur d'accéder plus rapidement à la valeur. Ce signe @ n’est pas nécessaire pour les registres x86 les plus courants. Pour les autres registres et pseudo-registres, nous vous recommandons d’ajouter l'arobase, mais cela n’est pas réellement nécessaire. Si vous omettez le signe arobase pour les registres moins courants, le débogueur essaie d'analyser le texte d'abord en tant que nombre hexadécimal, ensuite en tant que symbole, et finalement en tant que registre.
Vous pouvez également utiliser un point (.) pour indiquer le pointeur d’instruction actuel. Vous ne devez pas ajouter un signe @ avant cette période, et vous ne pouvez pas utiliser un point comme premier paramètre de la commande r. Cette période a la même signification que le pseudo-registre $ip .
Pour plus d’informations sur les registres et les pseudo-registres, consultez Syntaxe de registre et syntaxePseudo-Register.
Utilisez la commande r register pour voir que la valeur du @rip registre est 00007ffb'7ed00770.
0:000> r
rax=0000000000000000 rbx=0000000000000010 rcx=00007ffb7eccd2c4
rdx=0000000000000000 rsi=00007ffb7ed61a80 rdi=00000027eb6a7000
rip=00007ffb7ed00770 rsp=00000027eb87f320 rbp=0000000000000000
r8=00000027eb87f318 r9=0000000000000000 r10=0000000000000000
r11=0000000000000246 r12=0000000000000040 r13=0000000000000000
r14=00007ffb7ed548f0 r15=00000210ea090000
iopl=0 nv up ei pl zr na po nc
cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
ntdll!LdrpDoDebuggerBreak+0x30:
00007ffb`7ed00770 cc int 3
Cette même valeur peut être affichée à l’aide du fichier . Raccourci de point.
0:000> ? .
Evaluate expression: 140718141081456 = 00007ffb`7ed00770
Nous pouvons confirmer que ces valeurs sont toutes équivalentes et retournent zéro s’ils le sont, à l’aide de cette expression MASM.
0:000> ? NOT(($ip = .) AND ($ip = @rip) AND (@rip =. ))
Evaluate expression: 0 = 00000000`00000000
Numéros de ligne source dans les expressions MASM
Vous pouvez utiliser des expressions de fichier source et de numéro de ligne dans des expressions MASM. Vous devez placer ces expressions en utilisant des accents graves ('). Pour plus d’informations sur la syntaxe, consultez Syntaxe de ligne source.