x86, difference between BYTE and BYTE PTR
Solution 1:
Summary:
- NASM/YASM requires
word [ecx]
when the operand-size isn't implied by the other operand. (Otherwise[ecx]
is ok). - MASM/TASM requires
word ptr [ecx]
when the operand-size isn't implied by the other operand. (Otherwise[ecx]
is ok).
They each choke on the other's syntax.
WARNING: This is very strange area without any ISO standards or easy-to-find BNF tables; and I'm not an expert of walking through minefields of proprietary MASM syntax.
It your case there is may be no difference, but PTR operator can mean in other cases:
http://www.c-jump.com/CIS77/ASM/Instructions/I77_0250_ptr_pointer.htm
In general, PTR operator forces expression to be treated as a pointer of specified type:
.DATA
num DWORD 0
.CODE
mov ax, WORD PTR [num] ; Load a word-size value from a DWORD
I think, there are also assembler specific requirements (nasm/tasm/ other asm) and using of "byte ptr" is more portable.
Also check the section 4.2.16 in book from India and sections 8.12.3 (and 8.11.3 "Type Conflicts") in the "The Art of Assembly Language Programming".
UPDATE: thanks to Frank Kotler, seems that NASM "uses a variation of Intel assembly syntax" (wiki), which doesn't include PTR operation.
UPDATE1: There is original "ASM86 LANGUAGE REFERENCE MANUAL" from Intel, 1981-1983, PTR Operator is defined on page 4-15:
PTR Operator
Syntax: type PTR name
Description: The PTR operator is used to define a memory reference with a certain type. The assembler determines the correct instruction to assemble based on the type of the operands to the instruction. There are certain instances where you may specify an operand that has no type. These cases involve the use of numeric or register expressions. Here the PTR operator is used to specify the type of the operand. The following examples illustrate this use:
MOV WORD PTR [BX], 5 ;set word pointed to by BX = 5
INC DS:BYTE PTR 10 ;increment byte at offset 10
;from DS
This form can also be used to override the type attribute of a variable or label. If, for example, you wished to access an already defined word variable as two bytes, you could code the following:
MOV CL, BYTE PTR AWORD ;get first byte
MOV CL, BYTE PTR AWORD + 1 ;get second byte
Field Values:
type This field can have one of the following values: BYTE, WORD, DWORD, QWORD, TBYTE, NEAR, FAR
name This field can be: 1. A variable name. 2. A label name. 3. An address or register expression. 4. An integer that represents an offset.
UPDATE2: Thanks to Uni of Stuttgart's bitsaver! There is original MACRO-86 manual from Microsoft (1981). Page 3-7:
The PTR operator can be used another way to save yourself a byte when using forward references. If you defined FOO as a forward constant, you might enter the statement:
MOV [BX],FOO
You may want to refer to FOO as a byte immediate. In this case, you could enter either of the statements (they are equivalent):
MOV BYTE PTR [BX],FOO
MOV [BX],BYTE PTR FOO
These statements tell MACRO-86 that FOO is a byte immediate. A smaller instruction is generated.
And page 3-16:
Override operators
These operators are used to override the segment, offset, type, or distance of variables and labels.
Pointer (PTR)
<attribute> PTR <expression>
The PTR operator overrides the type (BYTE, WORD, DWORD) or the distance (NEAR, FAR) of an operand.
<attribute>
is the new attribute; the new type or new distance.
<expression>
is the operand whose attribute is to be overridden.The most important and frequent use for PTR is to assure that MACRO-86 understands what attribute the expression is supposed to have. This is especially true for the type attribute. Whenever you place forward references in your program, PTR will make clear the distance or type of the expression. This way you can avoid phase errors.
The second use of PTR is to access data by type other than the type in the variable definition. Most often this occurs in structures. If the structure is defined as WORD but you want to access an item as a byte, PTR is the operator for this. However, a much easier method is to enter a second statement that defines the structure in bytes, too. This eliminates the need to use PTR for every reference to the structure. Refer to the LABEL directive in Section 4.2.1, Memory Directives.
Examples:
CALL WORD PTR [BX][SI]
MOV BYTE PTR ARRAY, (something)
ADD BYTE PTR FOO,9
After reading this and looking to some syntax definitions from these documents I think that writing PTR is mandatory. Usage of mov BYTE [ecx], 0
is incorrect according to MACRO-86 manual.
Solution 2:
You are using a permissive assembler, it seems, my C compiler's support for in-line assembly sure isn't happy with it. The proper syntax is BYTE PTR to tell the assembler that the value in the ECX register should be treated like a pointer. PTR. But that's syntax that's over specified, it could already tell that you meant to use it as a pointer by you putting [brackets] around the register name. Using [ecx] already made it clear that you meant to store zero into the address provided by the ECX register.
So it knows how to use the ECX register, the only other thing it doesn't know is how many bytes need to be set to zero. Choices are 1, 2 or 4. You made it clear, 1. BYTE.
Solution 3:
In MASM, BYTE PTR [ecx] accesses memory at address ecx. BYTE [ecx] is a syntax error ("inline assembler syntax error in 'first operand'; found '['").
In NASM or YASM, BYTE [ecx] accesses memory at address ecx. BYTE PTR [ecx] is a syntax error ("error: comma, colon or end of line expected" in NASM, "undefined symbol `PTR'" in YASM).
In TASM, BYTE PTR [ecx] and BYTE [ecx] are equivalent--both access memory at address ecx.
However, in the Gnu assembler gas, when using the intel syntax BYTE PTR [ecx] accesses memory at ecx, but BYTE [ecx] actually accesses memory at address ecx+1. That is, BYTE [ecx] is equivalent to BYTE PTR [ecx+1], which does not appear to be either sane or documented.
Gnu assembler version 2.18, 2.24, or 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