10

想象一下,你在 10 年前写了这个(在英特尔 MPXbnd0..bnd3寄存器甚至在路线图上之前):

section .data

; define some globals which are part of an ABI so you can't just rename them
global bnd0      ; MPX bound register name conflict
bnd0: dd 123

global k0        ; AVX512 mask register name conflict
k0: dq 12345

您如何使用当前版本的 NASM 组装它? 即 NASM(或 YASM)是否与支持新寄存器名称的新版本具有前向兼容性?

显然,这很容易通过在单个文件或项目中搜索/替换来解决。但理论上,您可以将全局变量名作为库 ABI 的一部分,您可以从 NASM 导出或需要使用extern ymm0. (必须声明外部符号,因此无法识别的寄存器名称永远不会汇编为符号引用。)

NASM 语法已经不适合作为 C 编译器输出的格式在不使用 an 前缀符号名称_或进行一些其他类型的名称修饰(例如 Linux ELF)的平台上。您无法编译全局int eax = 1;. 这就是 AT&T 语法%eax用于寄存器名称的原因。对该答案的评论中的讨论激发了这个问题。请注意,GAS 不需要声明外部符号;无法识别的名称被视为符号(即使在.intel_syntax noprefix使用类似于 MASM 的语法的模式下)。

相关:MASM 如何处理新扩展的前向源兼容性?


你能以某种方式禁用 MPX 支持吗?

YASM 支持一个CPU指令,允许您禁用对某些助记符的支持,但即使禁用 AVX 支持也不允许您将ymm0其用作符号名称。(YASM 1.3.0 不支持 AVX512 或 MPX,因此它可以汇编使用这些寄存器名称作为符号的代码,但它确实支持 AVX2。)

CPU Conroe
extern ymm0

我明白了yasm-CPU.asm:2: error: directive 'extern' requires an identifier parameter。或者ymm0: dd 123,错误是yasm-CPU.asm:2: error: label or instruction expected at start of line

但是绝对禁用 AVX 支持:组装CPU Conroe/vmovaps xmm0, [edi]给出:

$ yasm -Worphan-labels -felf32 yasm-CPU.asm
yasm-CPU.asm:2: warning: `vmovaps' is an instruction in CPU
yasm-CPU.asm:2: error: instruction expected after label    

(它说CPU 686或类似的旧禁用扩展。IDK 为什么它不说in CPU Sandybridge AVX。似乎 yasm 不再得到很好的维护。YASM 1.3.0 支持CPU Haswelland AVX2,但文档没有提到它。)

此功能的目的是防止您在 SSSE3 或更低 CPU 的函数中意外使用 SSE4 指令,但显然它对解决此问题没有帮助。


NASM 的CPU指令似乎是相似的,也根本没有帮助:

CPU 686
vmovaps xmm0, [edi]
extern ymm0         
    mov eax, ymm0

$ nasm -Worphan-labels -felf32 CPU.asm 
CPU.asm:2: error: no instruction for this cpu level
CPU.asm:4: error: invalid combination of opcode and operands

请注意,无论extern ymm0有没有指令,它都可以很好地组装CPU,但是一旦将其用作操作数,就会出现问题。

4

1 回答 1

12

NASM 允许您在符号前加上美元符号$,以便将其解释为符号而不是寄存器或其他保留字。从NASM 文档

3.1 NASM 源代码行的布局

[...] 标识符也可以以 a 为前缀,$以表明它旨在作为标识符而不是保留字来阅读;因此,如果您要链接的某个其他模块定义了一个名为 的符号eax,您可以$eax在 NASM 代码中引用该符号以将该符号与寄存器区分开来。[...]

MASM 通常仅在 C 编译器使用下划线前缀标识符的环境中使用_,因此对于该汇编器来说这不是一个大问题。然而它确实有一个解决这个问题的方法,但它基本上与 NASM 的相反。您可以使用 OPTION NOKEYWORD 指令禁用您选择的保留字。例如,您可以使用OPTION NOKEYWORD:<eax>,以便您可以使用名为eax. 当然,这会阻止您使用名为 EAX 的寄存器,因此它不像 NASM 那样通用。

于 2017-08-26T01:04:50.590 回答