这两条线有什么区别? PTR在这里改变了什么?
;first
mov BYTE [ecx], 0
;second
mov BYTE PTR [ecx], 0
答案 0 :(得分:14)
摘要:
word [ecx]
。 (否则[ecx]
没问题。)word ptr [ecx]
。 (否则[ecx]
没问题。)他们每个人都会扼杀另一个人的语法。
警告:这是一个非常奇怪的区域,没有任何ISO标准或易于查找的BNF表;而且我不是走过专有MASM语法的雷区的专家。
你的情况可能没有区别,但PTR运营商在其他情况下可能意味着:
http://www.c-jump.com/CIS77/ASM/Instructions/I77_0250_ptr_pointer.htm
通常,PTR运算符强制将表达式视为指定类型的指针:
.DATA
num DWORD 0
.CODE
mov ax, WORD PTR [num] ; Load a word-size value from a DWORD
我认为,还有汇编程序特定的要求(nasm / tasm / other asm),使用“byte ptr”更加便携。
另请参阅“汇编语言编程的艺术”中的book from India和8.12.3部分(以及8.11.3“类型冲突”)中的4.2.16部分。
更新:感谢Frank Kotler,似乎NASM“使用了英特尔汇编语法的变体”(wiki),其中不包括PTR操作。
UPDATE1:英特尔有原始"ASM86 LANGUAGE REFERENCE MANUAL",1981-1983,第4-15页定义了PTR运营商:
PTR运营商
语法:输入PTR名称
描述:PTR运算符用于定义具有特定类型的内存引用。汇编程序根据指令的操作数类型确定要汇编的正确指令。在某些情况下,您可以指定没有类型的操作数。这些情况涉及使用数字或寄存器表达式。这里PTR运算符用于指定操作数的类型。以下示例说明了这种用法:
MOV WORD PTR [BX], 5 ;set word pointed to by BX = 5
INC DS:BYTE PTR 10 ;increment byte at offset 10
;from DS
此表单还可用于覆盖变量或标签的type属性。例如,如果您希望将已定义的单词变量作为两个字节访问,则可以编写以下代码:
MOV CL, BYTE PTR AWORD ;get first byte
MOV CL, BYTE PTR AWORD + 1 ;get second byte
字段值:
type此字段可以具有以下值之一:BYTE,WORD,DWORD,QWORD,TBYTE,NEAR,FAR
name此字段可以是:1。变量名称。 2.标签名称。 3.地址或寄存器表达式。 4.表示偏移量的整数。
UPDATE2:感谢斯图加特的Uni of the bitaver!微软有original MACRO-86 manual(1981)。第3-7页:
当使用前向引用时,可以使用PTR运算符以另一种方式保存自己的字节。如果您将FOO定义为前向常量,则可以输入以下语句:
MOV [BX],FOO
您可能希望立即将FOO称为字节。在这种情况下,您可以输入任一语句(它们是等效的):
MOV BYTE PTR [BX],FOO
MOV [BX],BYTE PTR FOO
这些语句告诉MACRO-86 FOO是一个字节立即。生成一条较小的指令。
第3-16页:
覆盖运营商
这些运算符用于覆盖变量和标签的分段,偏移,类型或距离。
指针(PTR)
<attribute> PTR <expression>
PTR运算符会覆盖操作数的类型(BYTE,WORD,DWORD)或距离(NEAR,FAR)。
<attribute>
是新属性;新类型或新距离。
<expression>
是要覆盖其属性的操作数。PTR最重要和最常用的是确保MACRO-86能够理解表达式应该具有的属性。对于type属性尤其如此。无论何时在程序中放置引用,PTR都会清楚表达的距离或类型。这样就可以避免相位误差。
PTR的第二个用途是通过变量定义中的类型以外的类型访问数据。大多数情况下,这发生在结构中如果结构定义为WORD但您想要将项目作为字节访问,则PTR是此操作符。但是,更简单的方法是输入第二个语句,该语句也以字节为单位定义结构。这消除了对结构的每个引用使用PTR的需要。请参见第4.2.1节“内存指令”中的LABEL指令。
示例:
CALL WORD PTR [BX][SI]
MOV BYTE PTR ARRAY, (something)
ADD BYTE PTR FOO,9
阅读本文并从这些文档中寻找一些语法定义后,我认为编写PTR是强制性的。根据MACRO-86手册,mov BYTE [ecx], 0
的使用不正确。
答案 1 :(得分:6)
你正在使用一个宽松的汇编程序,看来,我的C编译器对内联汇编的支持肯定不满意。正确的语法是BYTE PTR告诉汇编器ECX寄存器中的值应该被视为指针。 PTR。但是那个超过指定的语法,它已经可以告诉你,你想把它作为一个指针,你把[括号]放在寄存器名称周围。使用[ecx]已经明确表示您打算将零存储到ECX寄存器提供的地址中。
所以它知道如何使用ECX寄存器,唯一不知道的其他事情是需要将多少字节设置为零。选择是1,2或4.你说清楚了,1。BYTE。
答案 2 :(得分:0)
在MASM中,BYTE PTR [ecx]访问地址ecx处的内存。 BYTE [ecx]是一个语法错误(&#34;第一个操作数中的内联汇编语法错误&#39 ;;找到&#39; [&#39;&#34;)。
在NASM或YASM中,BYTE [ecx]访问地址ecx处的内存。 BYTE PTR [ecx]是语法错误(&#34;错误:逗号,冒号或行尾预期&#34;在NASM中,&#34;未定义符号`PTR&#39;&#34;在YASM中)。< / p>
在TASM中,BYTE PTR [ecx]和BYTE [ecx]是等效的 - 都是地址ecx的访问存储器。
然而,在Gnu汇编程序气体中,当使用英特尔语法时,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