wake-up-neo.com

x86, Differenz zwischen BYTE und BYTE PTR

Was ist der Unterschied zwischen diesen beiden Linien? Welche PTR ändert sich hier?

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

Zusammenfassung: 

  • NASM/YASM erfordert Word [ecx], wenn die Operandengröße nicht vom anderen Operanden übernommen wird. (Ansonsten ist [ecx] in Ordnung).
  • MASM/TASM erfordert Word ptr [ecx], wenn die Operandengröße nicht vom anderen Operanden übernommen wird. (Ansonsten ist [ecx] in Ordnung).

Sie ersticken an der Syntax des anderen.


WARNUNG: Dies ist ein sehr ungewöhnlicher Bereich ohne ISO-Standards oder leicht zu findende BNF-Tabellen. Ich bin kein Experte, wenn ich durch die Minenfelder der proprietären MASM-Syntax gehe.

In Ihrem Fall gibt es keinen Unterschied, aber der PTR-Operator kann in anderen Fällen Folgendes bedeuten:

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

Im Allgemeinen erzwingt der PTR-Operator, dass der Ausdruck als Zeiger des angegebenen Typs behandelt wird:

 .DATA
 num  DWORD   0

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

Ich denke, es gibt auch Assembler-spezifische Anforderungen (nasm/tasm/other asm) und die Verwendung von "byte ptr" ist tragbarer.

Siehe auch Abschnitt 4.2.16 in Buch aus Indien und Abschnitte 8.12.3 (und 8.11.3 "Typkonflikte") in "Die Kunst der Assembler-Sprachprogrammierung" .

UPDATE: Dank Frank Kotler scheint NASM "eine Variante der Intel Assembly-Syntax" (Wiki) zu verwenden, die keine PTR-Operation enthält.

UPDATE1: Es gibt Original "ASM86-SPRACHE-REFERENZHANDBUCH" von Intel, 1981-1983, PTR-Operator ist auf Seite 4-15 definiert:

PTR-Operator

Syntax: Geben Sie den PTR-Namen ein

Beschreibung: Mit dem PTR-Operator wird eine Speicherreferenz mit einem bestimmten Typ definiert. Der Assembler bestimmt die richtige Anweisung zum Assemblieren basierend auf dem Typ der Operanden für die Instruktion. In bestimmten Fällen können Sie einen Operanden angeben, der keinen Typ hat. In diesen Fällen werden numerische Ausdrücke oder Registerausdrücke verwendet. Hier wird der PTR-Operator verwendet, um den Typ des Operanden anzugeben. Die folgenden Beispiele veranschaulichen diese Verwendung:

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

Dieses Formular kann auch verwendet werden, um das type-Attribut einer Variablen oder eines Labels zu überschreiben. Wenn Sie beispielsweise auf eine bereits definierte Word-Variable als zwei Bytes zugreifen möchten, können Sie Folgendes eingeben:

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

Feldwerte:

type Dieses Feld kann einen der folgenden Werte annehmen: BYTE, Word, DWORD, QWORD, TBYTE, NEAR, FAR

name Dieses Feld kann Folgendes sein: 1. Ein Variablenname. 2. Ein Labelname. 3. Eine Adresse oder ein Registerausdruck. 4. Eine Ganzzahl, die einen Versatz darstellt.

UPDATE2: Danke an die Bitsaver von Uni von Stuttgart! Es gibt originales MACRO-86-Handbuch von Microsoft (1981). Seite 3-7:

Der PTR-Operator kann auf andere Weise verwendet werden, um sich bei Verwendung von Forward-Referenzen ein Byte zu sichern. Wenn Sie FOO als Vorwärtskonstante definiert haben, können Sie die Anweisung eingeben:

MOV [BX],FOO

Möglicherweise möchten Sie FOO als ein Byte unmittelbar bezeichnen. In diesem Fall können Sie eine der folgenden Anweisungen eingeben (sie sind gleichwertig):

MOV BYTE PTR [BX],FOO

MOV [BX],BYTE PTR FOO

Diese Anweisungen teilen MACRO-86 mit, dass es sich bei FOO um ein Byte handelt. Eine kleinere Anweisung wird generiert.

Und Seite 3-16:

Operatoren überschreiben

Diese Operatoren werden verwendet, um das Segment, den Versatz, den Typ oder den Abstand von Variablen und Beschriftungen zu überschreiben.

Zeiger (PTR)

<attribute>  PTR  <expression>

Der PTR-Operator überschreibt den Typ (BYTE, Word, DWORD) oder die Entfernung (NEAR, FAR) eines Operanden.

<attribute> ist das neue Attribut; der neue Typ oder die neue Entfernung.

<expression> ist der Operand, dessen Attribut überschrieben werden soll.

Die wichtigste und häufigste Verwendung von PTR ist es sicherzustellen, dass MACRO-86 versteht, welches Attribut der Ausdruck haben soll. Dies gilt insbesondere für das type-Attribut. Wenn Sie in Ihrem Programm Vorwärtsverweise setzen, macht PTR die Entfernung oder den Typ des Ausdrucks deutlich. Auf diese Weise können Sie Phasenfehler vermeiden.

Die zweite Verwendung von PTR ist der Zugriff auf Daten nach Typ, der nicht der Typ in der Variablendefinition ist. Meistens tritt dies in Strukturen auf. Wenn die Struktur als Word definiert ist, Sie jedoch als Byte auf ein Element zugreifen möchten, ist PTR der Operator dafür. Eine wesentlich einfachere Methode ist jedoch die Eingabe einer zweiten Anweisung, die die Struktur auch in Bytes definiert. Dadurch entfällt die Verwendung von PTR für jeden Verweis auf die Struktur. Weitere Informationen finden Sie in der LABEL-Direktive in Abschnitt 4.2.1, Speicherrichtlinien.

Beispiele:

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

 ADD BYTE PTR FOO,9

Nachdem ich dies gelesen und einige Syntaxdefinitionen aus diesen Dokumenten betrachtet habe, denke ich, dass das Schreiben von PTR zwingend ist. Die Verwendung von mov BYTE [ecx], 0 ist gemäß MACRO-86-Handbuch nicht korrekt.

13
osgx

Sie verwenden einen permissiven Assembler, es scheint, die Unterstützung meines C-Compilers für Inline-Assembly ist damit nicht zufrieden. Die richtige Syntax ist BYTE PTR, um dem Assembler mitzuteilen, dass der Wert im ECX-Register wie ein Zeiger behandelt werden soll. PTR. Aber das ist die Syntax, die über spezifiziert ist , sie konnte bereits erkennen, dass Sie sie als Zeiger verwenden wollten, indem Sie [Klammern] um den Registernamen setzen. Durch die Verwendung von [ecx] wurde bereits klargestellt, dass Sie die Null in der vom ECX-Register angegebenen Adresse speichern wollten.

Es weiß also, wie man das ECX-Register verwendet, die einzige andere Sache, die es nicht weiß, ist, wie viele Bytes auf Null gesetzt werden müssen. Zur Auswahl stehen 1, 2 oder 4. Sie haben klar gemacht, 1. BYTE.

6
Hans Passant

In MASM greift BYTE PTR [ecx] unter der Adresse ecx auf den Speicher zu. BYTE [ecx] ist ein Syntaxfehler ("Inline-Assembler-Syntaxfehler in 'erster Operand'; gefunden '['")).

In NASM oder YASM greift BYTE [ecx] auf den Speicher unter Adresse ecx zu. BYTE PTR [ecx] ist ein Syntaxfehler ("Fehler: Komma, Doppelpunkt oder Zeilenende erwartet" in NASM, "undefined Symbol" PTR "" in YASM).

In TASM sind BYTE PTR [ecx] und BYTE [ecx] gleichwertig - beide greifen auf Speicher an der Adresse ecx zu.

Im Gnu-Assembler-Gas greift BYTE PTR [ecx] bei Verwendung der Intel-Syntax jedoch auf Speicher bei ecx zu, aber BYTE [ecx] greift tatsächlich auf Speicher unter Adresse ecx + 1 zu. Das heißt, BYTE [ecx] ist gleichbedeutend mit BYTE PTR [ecx + 1], das weder als gesund noch als dokumentiert erscheint.

Gnu Assembler Version 2.18, 2.24 oder 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