Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

x86, difference between BYTE and BYTE PTR

What is the difference between these two lines? What PTR changes here?

;first
mov BYTE [ecx], 0  
;second
mov BYTE PTR [ecx], 0
like image 961
Linkas Avatar asked Dec 09 '12 18:12

Linkas


People also ask

What is a byte ptr?

byte ptr -> it simply means that you want to fetch a byte from the address. if it said word ptr or dword ptr , you would get a word or dword from the address in source index.

What does ptr do in assembly?

It stands for pointer. One instance where ptr doesn't quite make sense, is when pushing an immediate value, such as | push dword ptr 012345678h | . The syntax implies that a pointer is being pushed onto the stack, but the immediate value doesn't actually have to be a pointer.

What is dword in assembly?

DWORD defines 'size' of the memory location used for move operation. In you example, you'd be moving 0000000Ah (4 bytes) into memory location ESP+18h. As 0Ah is immediate value its size cannot be determined without using DWORD , WORD , BYTE or other similar qualifier.


2 Answers

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.

like image 169
osgx Avatar answered Oct 19 '22 16:10

osgx


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.

like image 34
Hans Passant Avatar answered Oct 19 '22 15:10

Hans Passant