2012-12-09 127 views
16

这两行有什么区别? PTR有哪些变化?x86,BYTE和BYTE的区别PTR

;first 
mov BYTE [ecx], 0 
;second 
mov BYTE PTR [ecx], 0 
+9

有没有区别。汇编程序只接受两种不同的方言。 –

+0

对于x86汇编上的问题+1。和@AkiSuihkonen,看起来像一个答案,而不是一个评论。 –

+1

Linkas,并且在这个问题中缺少非常重要的细节:使用什么汇编程序:MASM/TASM/NASM/YAMS或其他。以及它是如何使用的(在其中一些语言中有方言选项)。 – osgx

回答

12

总结:

  • NASM/YASM要求word [ecx]当操作数大小不是由另一个操作数暗示。 (否则[ecx]是好的)。
  • 当操作数大小不被其他操作数隐含时,MASM/TASM需要word ptr [ecx]。 (否则[ecx]是好的)。

他们每个都扼住对方的语法。


警告:这是非常奇怪的区域,没有任何ISO标准或易于查找的BNF表;而且我不是走过专有MASM语法雷区的专家。

它的情况下,有可能是没有什么区别,但PTR操作员可以在其他情况下意味着:

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 

我认为,也有汇编器的特殊要求(NASM/tasm/other asm)和“byte ptr”的使用更便于携带。

在“的汇编语言编程艺术”另外,还要检查节4.2.16在book from India和部分8.12.3(8.11.3和“冲突型”)。

更新:感谢Frank Kotler,似乎NASM“使用英特尔汇编语法的变体”(wiki),它不包括PTR操作。

UPDATE1:

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:由于有来自英特尔,1981-1983原始"ASM86 LANGUAGE REFERENCE MANUAL",PTR操作员是第4-15页的定义斯图加特的比特币大学!有微软公司的original MACRO-86 manual(1981)。第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.

和页面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 

阅读完本文后,从这些文档看一些语法定义,我认为写PTR是强制性的。根据MACRO-86手册,mov BYTE [ecx], 0的使用不正确。

+7

Nasm将在'PTR'上bar bar。 Masm/Tasm将会没有它。 –

+0

@弗兰克的评论应该真的是这里的答案,而不是这个善意的混乱...... ;-)如果你不介意,这是一个相当常见的问题,所以它可能值得回去重写/重新格式化这个答案的很大一部分(并且包括一个TL;最大清晰度的DR)。 –

+0

@Cody,嗨,其实我现在可以理解这个答案的任何内容(它更像我的个人笔记本,记录一些有趣的古代/博物馆手册的URL)。你可以帮助编辑它,重写它(可能转换为wiki)? – osgx

6

您使用的是宽容的汇编程序,看起来,我的C编译器对内联汇编的支持肯定是不满意的。正确的语法是BYTE PTR告诉汇编器,ECX寄存器中的值应该像指针一样对待。 PTR。但是,这是超过指定的的语法,它可能已经告诉你,你打算通过将[括号]放在寄存器名称周围作为指针使用它。使用[ecx]已经明确指出,您的意思是将零存储到ECX寄存器提供的地址中。

所以它知道如何使用ECX寄存器,只有其他的东西它不知道有多少字节需要设置为零。选择是1,2或4.你已经明确了,1. BYTE。

0

在MASM中,BYTE PTR [ecx]访问地址为ecx的存储器。 BYTE [ecx]是语法错误(“第一个操作数中的内联汇编语法错误;找到'['”)。

在NASM或YASM中,BYTE [ecx]访问地址为ecx的内存。 BYTE PTR [ecx]是语法错误(在NASM中为“错误:逗号,冒号或行结束符”,YASM中的未定义符号“PTR”)。

在TASM中,BYTE PTR [ecx]和BYTE [ecx]是等效的 - 两个访问存储器都在地址ecx处。但是,在Gnu汇编语气中,当使用intel语法时,BYTE PTR [ecx]在ecx访问内存,但BYTE [ecx]实际访问地址为ecx + 1的内存。也就是说,BYTE [ecx]相当于BYTE PTR [ecx + 1],它看起来既不健全也不记录。

GNU汇编版本2.18,2.24,或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 
+1

在GNU汇编器中,标识符BYTE,WORD,DWORD是也像定义1,2,4'movb BYTE [ecx],0'实际上与'movb 1 [ecx],0'一样,它是'mov BYTE PTR [ecx + 1],0'。 'movb WORD [ecx],0'与'movb 2 [ecx],0'或'mov BYTE PTR [ecx + 2],0'相同。 'mov eax,WORD'与'mov eax,2'相同。 'mov eax,BYTE'和'mov eax,1'等一样。 –

+0

有趣,谢谢! “mov ecx,BYTE”是NASM,MASM和TASM中的语法错误,但不是气。 –