Assembly x86,字节和字节PTR之间的差异

Assembly x86,字节和字节PTR之间的差异,assembly,x86,nasm,masm,Assembly,X86,Nasm,Masm,这两条线有什么区别?PTR在这里有什么变化 ;first mov BYTE [ecx], 0 ;second mov BYTE PTR [ecx], 0 总结: 当操作数大小不是由另一个操作数暗示时,NASM/YASM需要word[ecx]。(否则[ecx]就可以了) 当操作数大小不是由另一个操作数暗示时,MASM/TASM需要字ptr[ecx]。(否则[ecx]就可以了) 他们每个人都对对方的语法感到窒息 警告:这是一个非常奇怪的区域,没有任何ISO标准或容易找到BNF表;我不是一

这两条线有什么区别?PTR在这里有什么变化

;first
mov BYTE [ecx], 0  
;second
mov BYTE PTR [ecx], 0
总结:

  • 当操作数大小不是由另一个操作数暗示时,NASM/YASM需要
    word[ecx]
    。(否则
    [ecx]
    就可以了)
  • 当操作数大小不是由另一个操作数暗示时,MASM/TASM需要
    字ptr[ecx]
    。(否则
    [ecx]
    就可以了)
他们每个人都对对方的语法感到窒息


警告:这是一个非常奇怪的区域,没有任何ISO标准或容易找到BNF表;我不是一个穿越专有MASM语法雷区的专家

在您的情况下可能没有区别,但PTR操作员在其他情况下可能意味着:

通常,PTR运算符强制将表达式视为指定类型的指针:

我认为,还有特定于汇编程序的需求(nasm/tasm/other asm),使用“byte ptr”更便于移植

同时检查“汇编语言编程的艺术”中的第4.2.16节和第8.11.3节“类型冲突”

更新:多亏了Frank Kotler,NASM似乎“使用了英特尔汇编语法的变体”(wiki),其中不包括PTR操作

更新1:有来自英特尔的原件,1981-1983,PTR运算符定义见第4-15页:

PTR操作员

语法:键入PTR name

描述:PTR运算符用于定义具有特定类型的内存引用。汇编程序根据指令的操作数类型确定要汇编的正确指令。在某些情况下,可以指定没有类型的操作数。这些情况涉及数字或寄存器表达式的使用。这里,PTR运算符用于指定操作数的类型。以下示例说明了此用途:

此表单还可用于重写变量或标签的类型属性。例如,如果希望以两个字节的形式访问已定义的word变量,可以编写以下代码:

字段值:

键入此字段可以有以下值之一:字节、字、DWORD、QWORD、TBYTE、近、远

此字段的名称可以是:1。变量名。2.标签名称。3.地址或寄存器表达式。4.表示偏移量的整数

更新2:感谢斯图加特大学的bitsaver!微软公司(1981年)发布了一份报告。第3-7页:

当使用正向引用时,PTR运算符可以用另一种方式为自己保存一个字节。如果将FOO定义为正向常量,则可以输入以下语句:

您可能希望将FOO称为字节立即数。在这种情况下,您可以输入以下任一语句(它们是等效的):

这些语句告诉宏86 FOO是一个字节立即数。生成一条较小的指令

第3-16页:

覆盖运算符

这些运算符用于替代变量和标签的线段、偏移、类型或距离

指针(PTR)


在阅读了本文并查看了这些文档中的一些语法定义之后,我认为编写PTR是必须的。根据MACRO-86手册,mov字节[ecx],0的用法不正确。

您使用的是一个允许的汇编程序,我的C编译器对内嵌汇编的支持似乎并不满意。正确的语法是BYTE PTR,用于告诉汇编程序ECX寄存器中的值应被视为指针。PTR。但这是过度指定的语法,通过在寄存器名周围加上[括号],它可能已经表明您打算将其用作指针。使用[ecx]已经清楚地表明,您打算将零存储到ecx寄存器提供的地址中


所以它知道如何使用ECX寄存器,唯一不知道的是需要将多少字节设置为零。选择是1、2或4。你说得很清楚,1。字节。

在MASM中,字节PTR[ecx]访问地址ecx处的内存。字节[ecx]是一个语法错误(“第一个操作数中的内联汇编程序语法错误;找到“[”)

在NASM或YASM中,字节[ecx]访问地址ecx处的内存。字节PTR[ecx]是一个语法错误(“错误:在NASM中应为逗号、冒号或行尾”,在YASM中为未定义的符号“PTR”)

在TASM中,字节PTR[ecx]和字节[ecx]是等效的——都访问地址ecx处的内存

然而,在Gnu汇编程序gas中,当使用intel语法时,字节PTR[ecx]访问ecx处的内存,但字节[ecx]实际上访问地址ecx+1处的内存。也就是说,字节[ecx]相当于字节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

cat>foo.S没有区别。汇编程序只接受两种不同的方言。对于x86汇编上的一个问题+1。和@akishuihkonen,这看起来像是一个答案而不是一个注释。Linkas,问题中缺少一个非常重要的细节:使用了什么汇编程序:MASM/TASM/NASM/YAMS或其他什么。它是如何使用的(有些问题中有方言选项)。虽然是一个老问题(现在又出现了),但这个问题是关于GNU汇编程序(as)的吗使用不带前缀的英特尔语法?如果不是问汇编程序的问题的话?Nasm会在
PTR
上呕吐。Masm/Tasm会在没有前缀的情况下呕吐。@Frank的评论应该是这里真正的答案,而不是这个善意的混乱…;-)如果你不介意的话,这是一个非常常见的问题,因此可能值得回头看看太长了,读不下去了。(Cody,嗨,实际上我现在能理解这个答案的任何内容(它更像我的个人笔记本,把一些URL记录到一些有趣的古董/博物馆手册)。你能帮助改写它吗?(很可能转换为维基)。我基本上写了一个n
MOV  WORD  PTR  [BX], 5        ;set word pointed to by BX = 5
INC  DS:BYTE  PTR  10          ;increment byte at offset 10
                               ;from DS
MOV  CL, BYTE  PTR AWORD       ;get first byte
MOV  CL, BYTE  PTR AWORD + 1   ;get second byte
MOV [BX],FOO
MOV BYTE PTR [BX],FOO

MOV [BX],BYTE PTR FOO
<attribute>  PTR  <expression>
 CALL WORD PTR [BX][SI]
 MOV BYTE PTR ARRAY, (something)

 ADD BYTE PTR FOO,9
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