x86 Assembly助记符标准吗?

时间:2019-01-25 16:56:37

标签: assembly x86 standards

x86标准是否包含助记符或仅定义操作码?

如果不包括它们,那么对于不同的汇编程序是否还有另一个标准?

2 个答案:

答案 0 :(得分:10)

助记符没有标准化,并且不同的汇编程序使用不同的助记符。一些例子:

  • AT&T样式的汇编程序将后缀callPythonScriptbwl应用于所有助记符,以指示操作数的大小。英特尔风格的汇编程序通常使用关键字qbyteworddword
  • 来表示这一点。
  • AT&T样式的汇编器可识别qwordcbtwcwtlcltq,而Intel样式的汇编器可识别与cqto,{{ 1}},cbwcwd
  • AT&T样式的汇编器可以识别cdqcqo,其中movz??是Intel样式的汇编器称为movs????和{的两个大小后缀。 {1}}
  • 某些Intel样式的汇编器也仅将movzx识别为movsx,而其他人也将movsxd识别为该指令的变体。
  • Plan 9样式的汇编器(例如Go中使用的汇编器)很奇怪,并且在很多方面都存在差异,例如使用Motorola样式的助记符进行条件跳转
  • 从历史上看,为8086的NEC V20克隆提供的NEC汇编程序带有几乎完全不同的助记符。例如,63 /r被称为movsxd

答案 1 :(得分:3)

不幸的是,实际上并没有一个书面的“ x86标准”能够定义CPU必须满足的最低要求才能成为x86。

英特尔的文档非常接近 “ x86标准”,但是在某些情况下,它提供的保证要比现代AMD CPU强大。例如英特尔保证1/2/4/8字节加载或从/到可缓存内存的原子存储,且对齐方式不得超出缓存行边界。但是AMD只保证不跨越8字节边界的可缓存加载/存储。

Why is integer assignment on a naturally aligned variable atomic on x86?引用了Intel的手册,显示所有保证均以“ Intel486处理器(及以后的较新处理器)”作为保证。没有提供适用于所有 x86 CPU(或更重要的是所有x86-64 CPU)的基准。我认为实际上x86(包括x86-64之前的版本)的实际共享基准是1字节,因为8088。

因此,要在现代x86-64 CPU上运行的软件不能假定8字节加载/存储具有原子性,除非它们实际对齐。我认为我们都可以同意原子性保证是成为现代多核x86 CPU的重要组成部分。即使在单个内核上,未缓存的MMIO访问的原子性也很重要。现代英特尔和AMD对此表示同意,但英特尔再次仅以“奔腾及其后继处理器”的形式对其进行记录。暗指“后来的 Intel 处理器”。


这就是说,英特尔文档确实为每个操作码定义了助记符,并注册了名称。在所有这些方面,AMD的文档均与英特尔的文档保持一致。

请参阅Intel's x86 Software Development Manuals的第2卷。可以在https://www.felixcloutier.com/x86/index.htmlhttps://github.com/HJLebbink/asm-dude/wiki上找到仅按指令手册条目的HTML摘录(没有解释符号和指令格式的部分),其他地方的旧版本格式也不同。


正如@fuz解释的那样,大多数汇编程序都选择遵循此标准,但这不是必需的。重要的部分是二进制兼容性,而不是asm源兼容性。

英特尔必须为指令分配名称,以便它可以在其其余手册中用英语谈论它们,而不是因为它们需要世界上每个人都使用相同的asm语法。


我不确定英特尔的手册是否甚至完整定义了完整的asm语法(例如,如何在寻址模式下指示段覆盖前缀)。

在某些情况下,他们所做的工作远远超出了描述哪个机器代码做什么的范围,例如在字符串指令lods / stos / movs / cmps / scas(可能还有ins / outs)中,您会在Intel的vol.2手册中找到类似这样的段落:

  

在汇编代码级别,此指令的两种形式允许使用:“显式操作数”形式和“无操作数”形式。显式操作数形式(使用MOVS助记符指定)允许显式指定源和目标操作数。此处,源和目标操作数应该是分别指示源值和目标的大小和位置的符号。提供此显式操作数形式是为了允许文档;但是,请注意,此表格提供的文档可能会产生误导。也就是说,源和目标操作数符号必须指定操作数(字节,单词或双字)的正确的类型(大小),但不必指定正确的位置< / strong>。源操作数和目标操作数的位置始终由DS:(E)SI和ES:(E)DI寄存器指定,必须在执行移动字符串指令之前正确加载它们。

     

(突出显示(an HTML extract of)原始PDF)

某些“ Intel语法”汇编程序(例如NASM)会忽略此设置,仅允许将大小为movs的{​​{1}}用作助记符,例如movsb。 NASM还具有用于指示段覆盖前缀(例如fs lodsd)的语法,该前缀不需要操作数,因此,这完全避免了使用指示错误的内存操作数但仍会汇编的操作数的可能性。

(字符串指令仅使用隐式内存操作数,而不使用ModR / M寻址模式。)

NASM: parser: instruction expected rep movs

Convert Instruction in assembly code lods and stos so NASM can compile


是的,Intel-syntax汇编有多种形式,更不用说AT&T这样的语法了。

AT&T有意对某些指令使用不同的助记符,甚至将一些共享Intel语法助记符的操作码拆分为单独的助记符,例如movzb表示movzx,带有字节源,以及movzw表示词源版本。 (通常也使用大小后缀,例如movzbl,但也可以根据需要从32位目标寄存器中推断出l。)

与两个寄存器操作数a syntax design bug we're stuck with一起使用时,AT&T语法无意中fsubrfsub交换。 (幸运的是,x87总体上已经过时了。)