x86 Assemblée des pointeurs
espère que ce n'est pas une question stupide, mais je suis en train d'envelopper mon esprit autour de pointeurs dans l'assemblée.
Quelle est exactement la différence entre:
mov eax, ebx
et
mov [eax], ebx
et quand doit - dword ptr [eax]
doit être utilisé?
Aussi, quand j'ai essayer de faire mov eax, [ebx]
j'obtiens une erreur de compilation, pourquoi est-ce?
mov eax, ebx
se déplace de la valeur dans le registre E EAX . Le mov [eax], ebx
déplace la valeur de 32 bits dans E à l'emplacement de mémoire que EAX pointe à.Ok, donc juste pour s'assurer que je suis à la compréhension de ce correctement. Le code suivant:
int a; _asm { mov [a], eax
copie la valeur stockée dans eax dans l'emplacement de mémoire qui int un vers? Si je procéder pour imprimer la valeur de a, puis-je voir la valeur qui a été stocké dans eax? Aussi, si je ne la suivant à la place: int a = 5; _asm{ mov [eax], a
Ce qui se passe là-bas? Eax stockage de l'emplacement de la mémoire de l'un? ou est-ce le stockage de 5?Il n'est pas aussi simple que cela. Si nous supposons que
a
est une variable, alors mov [a],ebx
va écrire la valeur dans ebx à cette variable (a
est considérée comme une adresse trop). Certains compilateurs permettent également mov a,ebx
à faire de même, d'autres pas. Mais eax
est un registre, de sorte qu'il n'est pas une variable. mov [eax],ebx
n'est pas le même que mov eax,ebx
. Le premier magasin ebx à l'adresse pointée par eax, ce dernier va stocker ebx dans eax.Rudy je pense que vous venez peut-être éclairci un énorme point de confusion pour moi. Je suis à l'aide de Visual Studio (assembly en ligne) et a été à essayer de comprendre la différence entre
mov a, eax
et mov [a], eax
. Lorsque l'on regarde les registres et les valeurs locales ils étaient tous identiques... vous dites qu'ils sont identiques? Grand savoir!Dans MASM syntaxe les crochets
[]
sont ignorés, sauf si elles contiennent le nom d'un registre.OriginalL'auteur Duxa | 2017-05-03
Vous devez vous connecter pour publier un commentaire.
Comme cela a déjà été indiqué, l'emballage des crochets autour d'un opérande signifie que l'opérande est à déréférencé, comme s'il s'agissait d'un pointeur dans C. En d'autres termes, les parenthèses signifient que vous êtes la lecture d'une valeur de (ou le stockage d'une valeur en) cet emplacement de la mémoire, plutôt que de lire cette valeur directement.
Donc, c':
simplement des copies de la valeur dans
ebx
eneax
. Dans un pseudo-notation C, ce serait:eax = ebx
.Alors que ce:
déréférence le contenu de
ebx
et les magasins de la pointe-de valeur danseax
. Dans un pseudo-notation C, ce serait:eax = *ebx
.Enfin, ce:
stocke la valeur dans
ebx
dans l'emplacement mémoire pointé pareax
. Encore une fois, en pseudo-C notation:*eax = ebx
.Les registres ici pourrait aussi être remplacé par de la mémoire opérandes, comme la symbolique des noms de variables. Donc:
déréférence l'adresse de la variable
myVar
et les magasins de la contenu de cette variable dans laeax
, commeeax = myVar
.En revanche, ce:
magasins de la adresse de la variable
myVar
eneax
, commeeax = &myVar
.Au moins, c'est comment plus assembleurs de travail. Microsoft assembleur (appelé MASM), et Microsoft C/C++ compilateur de l'assembly en ligne, est un peu différent. Il traite les deux instructions ci-dessus comme l'équivalent, essentiellement ignorant les crochets autour de la mémoire des opérandes.
Pour obtenir l'adresse d'une variable dans MASM, vous devez utiliser la
OFFSET
mot-clé:Cependant, même si MASM a cette pardonner syntaxe et vous permet d'être bâclée, vous ne devriez pas. Toujours inclure les crochets quand vous voulez pour déréférencer une variable et obtenez sa valeur réelle. Vous n'obtiendrez jamais le mauvais résultat si vous écrivez le code explicitement à l'aide de la syntaxe appropriée, et il sera plus facile à comprendre pour les autres. De Plus, vous pouvez vous forcer à prendre l'habitude d'écrire le code de la manière que les autres assembleurs vont s'attendre à ce qu'il soit écrit, plutôt que de compter sur MASM de "faire ce que je veux dire, pas ce que j'écris" béquille.
Parlant de "faire ce que je veux dire, pas ce que j'écris" béquille, MASM aussi permet généralement de s'en tirer avec l'omission de l'opérande-spécificateur de taille, puisqu'il connaît la taille de la variable. Mais encore une fois, je recommande écrit pour plus de clarté et de cohérence. Par conséquent, si
myVar
est unint
, vous feriez:ou
Cette notation est nécessaire dans d'autres assembleurs comme MSNA qui ne sont pas fortement typé et n'oubliez pas que
myVar
est unDWORD
de la taille d'emplacement de mémoire.Vous n'en avez pas besoin à tout moment d'être déréférencé registre des opérandes, puisque le nom de ce registre indique sa taille.
al
etah
sont toujoursBYTE
de taille,ax
est toujoursWORD
de taille,eax
est toujoursDWORD
de la taille, etrax
est toujoursQWORD
de taille. Mais il ne fait pas de mal à inclure de toute façon, si vous le souhaitez, pour plus de cohérence avec la façon dont vous transcrire la mémoire des opérandes.Euh...vous ne devriez pas. Cette assemble très bien pour moi dans MSVC inline assemblée. Comme nous l'avons déjà vu, c'est équivalent à:
et signifie que l'emplacement mémoire pointé par
ebx
va être déréférencé et queDWORD
de la taille de la valeur sera chargé danseax
.Pas. Cette combinaison d'opérandes n'est pas autorisé. Comme vous pouvez le voir à partir de la documentation pour le
MOV
enseignement, il existe essentiellement cinq possibilités (en ignorant suppléant codages et segments):Avis qu'il n'est pas
mov memory, memory
, qui est ce que vous essayiez.Cependant, vous pouvez faire
a
point à ce qu'eax
se pointant simplement de codage:Maintenant
a
eteax
ont la même valeur. Sieax
est un pointeur, puisa
est maintenant un pointeur vers le même emplacement mémoire.Si vous souhaitez définir
a
à la valeur queeax
pointe, alors vous aurez à faire:Bien sûr, ce clobbers le pointeur et la remplace par la valeur déréférencée. Si vous ne voulez pas perdre le pointeur, alors vous aurez à utiliser une deuxième sorte de "scratch" registre; quelque chose comme:
Je me rends compte de tout ceci est un peu confus. Le
mov
instruction est surchargé avec un grand nombre de significations possibles dans le x86 ISA. Cela est dû à x86 de base d'une architecture CISC. En revanche, moderne architectures RISC faire un meilleur travail de séparation de registre-registre des mouvements, la mémoire des charges, de mémoire et de magasins. x86 crams dans un seul et uniquemov
instruction. Il est trop tard pour revenir en arrière et corriger; vous avez juste à obtenir à l'aise avec la syntaxe, et parfois, il faut un deuxième coup d'œil.incroyable que vous pouvez écrire plusieurs paragraphes expliquant l'opérateur de déréférencement
OriginalL'auteur Cody Gray