web-dev-qa-db-fra.com

x86, différence entre BYTE et BYTE PTR

Quelle est la différence entre ces deux lignes? Qu'est-ce que PTR change ici?

;first
mov BYTE [ecx], 0  
;second
mov BYTE PTR [ecx], 0
17
Linkas

Résumé: 

  • NASM/YASM requiert Word [ecx] lorsque la taille de l'opérande n'est pas impliquée par l'autre opérande. (Sinon, [ecx] est ok).
  • MASM/TASM requiert Word ptr [ecx] lorsque la taille de l'opérande n'est pas impliquée par l'autre opérande. (Sinon, [ecx] est ok).

Chacun s'étouffe avec la syntaxe de l'autre.


AVERTISSEMENT: Ceci est une zone très étrange sans normes ISO ou tables BNF faciles à trouver; et je ne suis pas un expert pour parcourir les champs de mines de la syntaxe propriétaire MASM.

Si votre cas n’y a peut-être pas de différence, l’opérateur PTR peut signifier dans d’autres cas:

http://www.c-jump.com/CIS77/ASM/Instructions/I77_0250_ptr_pointer.htm

En général, l'opérateur PTR force l'expression à être traitée comme un pointeur du type spécifié:

 .DATA
 num  DWORD   0

 .CODE
 mov     ax, Word PTR [num] ; Load a Word-size value from a DWORD

Je pense qu'il y a aussi des exigences spécifiques aux assembleurs (nasm/tasm/other asm) et que l'utilisation de "octet ptr" est plus portable.

Consultez également la section 4.2.16 dans livre indien et les sections 8.12.3 (et 8.11.3 "Conflits de types") dans "La programmation du langage d'assemblage}" .

UPDATE: grâce à Frank Kotler, il semble que NASM "utilise une variante de la syntaxe Intel Assembly" (wiki), qui n'inclut pas l'opération PTR.

UPDATE1: L'original "MANUEL DE RÉFÉRENCE LINGUISTIQUE ASM86}" d'Intel, 1981-1983, l'opérateur PTR est défini à la page 4-15:

Opérateur PTR

Syntaxe: tapez le nom du PTR

Description: L’opérateur PTR permet de définir une référence en mémoire avec un certain type. L'assembleur détermine l'instruction correcte à assembler en fonction du type des opérandes à l'instruction. Dans certains cas, vous pouvez spécifier un opérande sans type. Ces cas impliquent l'utilisation d'expressions numériques ou de registre. Ici, l'opérateur PTR est utilisé pour spécifier le type de l'opérande. Les exemples suivants illustrent cette utilisation:

MOV  Word  PTR  [BX], 5        ;set Word pointed to by BX = 5
INC  DS:BYTE  PTR  10          ;increment byte at offset 10
                               ;from DS

Ce formulaire peut également être utilisé pour remplacer l'attribut type d'une variable ou d'une étiquette. Si, par exemple, vous souhaitez accéder à une variable Word déjà définie sous forme de deux octets, vous pouvez coder ce qui suit:

MOV  CL, BYTE  PTR AWORD       ;get first byte
MOV  CL, BYTE  PTR AWORD + 1   ;get second byte

Valeurs de champ:

type Ce champ peut avoir l'une des valeurs suivantes: BYTE, Word, DWORD, QWORD, TBYTE, NEAR, FAR

name Ce champ peut être: 1. Un nom de variable. 2. Un nom d'étiquette. 3. Une adresse ou une expression de registre. 4. Un entier qui représente un décalage.

UPDATE2: Merci à bitsaver de Uni of Stuttgart! Il existe le manuel MACRO-86 d'origine de Microsoft (1981). Page 3-7:

L'opérateur PTR peut être utilisé d'une autre manière pour vous épargner un octet lorsque vous utilisez des références en aval. Si vous définissez FOO comme une constante avant, vous pouvez entrer la déclaration suivante:

MOV [BX],FOO

Vous voudrez peut-être vous référer à FOO comme un octet immédiat. Dans ce cas, vous pouvez entrer l’une ou l’autre des déclarations (elles sont équivalentes):

MOV BYTE PTR [BX],FOO

MOV [BX],BYTE PTR FOO

Ces déclarations indiquent à MACRO-86 que FOO est un octet immédiat. Une instruction plus petite est générée.

Et page 3-16:

Remplacer les opérateurs

Ces opérateurs permettent de remplacer le segment, le décalage, le type ou la distance des variables et des libellés.

Pointeur (PTR)

<attribute>  PTR  <expression>

L'opérateur PTR substitue le type (BYTE, Word, DWORD) ou la distance (NEAR, FAR) d'un opérande.

<attribute> est le nouvel attribut; le nouveau type ou la nouvelle distance.

<expression> est l'opérande dont l'attribut doit être remplacé.

L'utilisation la plus importante et la plus fréquente de PTR est de s'assurer que MACRO-86 comprend l'attribut que l'expression est supposée avoir. Cela est particulièrement vrai pour l'attribut type. Chaque fois que vous placez des références en avant dans votre programme, PTR indique clairement la distance ou le type de l'expression. De cette façon, vous pouvez éviter les erreurs de phase.

La deuxième utilisation de PTR est d’accéder à des données par type autre que le type de la définition de variable. Le plus souvent, cela se produit dans les structures. Si la structure est définie en tant que Word mais que vous souhaitez accéder à un élément sous forme d'octet, PTR en est l'opérateur. Cependant, une méthode beaucoup plus simple consiste à entrer une deuxième instruction définissant également la structure en octets. Ceci élimine le besoin d'utiliser PTR pour chaque référence à la structure. Reportez-vous à la directive LABEL dans la Section 4.2.1, Directives relatives à la mémoire.

Exemples:

 CALL Word PTR [BX][SI]
 MOV BYTE PTR ARRAY, (something)

 ADD BYTE PTR FOO,9

Après avoir lu ceci et examiné certaines définitions de syntaxe de ces documents, je pense que l’écriture de PTR est obligatoire. L'utilisation de mov BYTE [ecx], 0 est incorrecte selon le manuel MACRO-86.

13
osgx

Vous utilisez un assembleur permissif, semble-t-il, le support de mon compilateur C pour un assemblage en ligne ne vous décevra certainement pas. La syntaxe appropriée est BYTE PTR pour indiquer à l’assembleur que la valeur du registre ECX doit être traitée comme un pointeur. PTR. Mais c'est la syntaxe qui est sur spécifiée , elle pourrait déjà indiquer que vous vouliez l'utiliser comme un pointeur en mettant des [crochets] autour du nom du registre. Utiliser [ecx] indiquait déjà clairement que vous vouliez stocker zéro dans l'adresse fournie par le registre ECX.

Donc, il sait comment utiliser le registre ECX, la seule chose qu'il ne sait pas , c'est combien d'octets doivent être mis à zéro. Vous avez le choix entre 1, 2 ou 4. Vous avez bien précisé, 1. BYTE.

6
Hans Passant

Dans MASM, BYTE PTR [ecx] accède à la mémoire à l'adresse ecx. BYTE [ecx] est une erreur de syntaxe ("erreur de syntaxe de l'assembleur inline dans" premier opérande "; trouvé" ["")).

Dans NASM ou YASM, BYTE [ecx] accède à la mémoire à l'adresse ecx. BYTE PTR [ecx] est une erreur de syntaxe ("erreur: virgule, deux-points ou fin de ligne attendue" dans NASM, "symbole non défini" PTR "" dans YASM).

Dans TASM, BYTE PTR [ecx] et BYTE [ecx] sont équivalents - les deux ont accès à la mémoire à l'adresse ecx.

Cependant, dans le gaz d'assembleur Gnu, lorsque vous utilisez la syntaxe intel, BYTE PTR [ecx] accède à la mémoire à ecx, mais BYTE [ecx] accède à la mémoire à l'adresse ecx + 1. En d'autres termes, BYTE [ecx] est équivalent à BYTE PTR [ecx + 1], qui ne semble pas être sain d'esprit ni documenté.

Gnu assembler version 2.18, 2.24 ou 2.26.1:

cat > foo.S << EOF
.intel_syntax noprefix
 movb BYTE [ecx], 0 
 movb BYTE PTR [ecx], 0 
.att_syntax prefix
EOF

as foo.S
objdump -dM intel a.out

0:  67 c6 41 01 00          mov    BYTE PTR [ecx+0x1],0x0
5:  67 c6 01 00             mov    BYTE PTR [ecx],0x0
0
Orion Lawlor