符号名称与新 NASM 版本中的新寄存器名称冲突?
Symbol name conflicts with new register names in new NASM versions?
想象一下你在 10 年前写了这篇文章(在 Intel MPX 和 bnd0
..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 的当前版本 assemble? 即 NASM(或 YASM)是否向前兼容支持新注册名称的新版本?
显然,在单个文件或项目中使用 search/replace 很容易解决这个问题。但理论上,您可以将全局变量名称作为库 ABI 的一部分,您可以从 NASM 导出或需要 将 导入 NASM 并使用 extern ymm0
。 (必须声明外部符号,因此无法识别的寄存器名称永远不会 assemble 到符号引用。)
NASM 语法已经不适合作为平台上 C 编译器输出的格式,这些平台不使用 _
前缀符号名称或进行其他类型的名称修改(例如 Linux精灵)。您无法编译全局 int eax = 1;
。 。对该答案的评论中的讨论激发了这个问题。请注意,GAS 不需要声明外部符号;无法识别的名称被视为符号(即使在使用类似于 MASM 语法的 .intel_syntax noprefix
模式下)。
相关:MASM 如何处理新扩展的前向源兼容性?
你能以某种方式禁用 MPX 支持吗?
YASM supports a CPU
directive 允许您禁用对某些助记符的支持,但即使禁用 AVX 支持也不会让您使用 ymm0
作为符号名称。 (YASM 1.3.0 不支持 AVX512 或 MPX,因此它可以 assemble 使用这些寄存器名称作为符号的代码,但它确实支持 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 Haswell
和 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
请注意,无论是否使用 CPU
指令,它 assemble extern ymm0
都很好,但是一旦将其用作操作数,就会出现问题。
NASM 允许您在符号前加上美元符号 $
,以便它被解释为符号而不是寄存器或其他保留字。来自 NASM documentation:
3.1 Layout of a NASM Source Line
[...] An identifier may also be prefixed with a $
to indicate that it is intended to be read as an identifier and not a reserved word; thus, if some other module you are linking with defines a symbol called eax
, you can refer to $eax
in NASM code to distinguish the symbol from the register. [...]
MASM 通常仅用于 C 编译器使用下划线作为标识符前缀的环境 _
,因此对于该汇编器来说这不是什么大问题。然而它确实有解决这个问题的方法,但它基本上与 NASM 的相反。您可以使用 OPTION NOKEYWORD 指令来禁用您选择的保留字。例如,您可以使用 OPTION NOKEYWORD:<eax>
,这样您就可以使用名为 eax
的符号。当然,这会阻止您使用名为 EAX 的寄存器,因此它不像 NASM 那样通用。
想象一下你在 10 年前写了这篇文章(在 Intel MPX 和 bnd0
..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 的当前版本 assemble? 即 NASM(或 YASM)是否向前兼容支持新注册名称的新版本?
显然,在单个文件或项目中使用 search/replace 很容易解决这个问题。但理论上,您可以将全局变量名称作为库 ABI 的一部分,您可以从 NASM 导出或需要 将 导入 NASM 并使用 extern ymm0
。 (必须声明外部符号,因此无法识别的寄存器名称永远不会 assemble 到符号引用。)
NASM 语法已经不适合作为平台上 C 编译器输出的格式,这些平台不使用 _
前缀符号名称或进行其他类型的名称修改(例如 Linux精灵)。您无法编译全局 int eax = 1;
。 .intel_syntax noprefix
模式下)。
相关:MASM 如何处理新扩展的前向源兼容性?
你能以某种方式禁用 MPX 支持吗?
YASM supports a CPU
directive 允许您禁用对某些助记符的支持,但即使禁用 AVX 支持也不会让您使用 ymm0
作为符号名称。 (YASM 1.3.0 不支持 AVX512 或 MPX,因此它可以 assemble 使用这些寄存器名称作为符号的代码,但它确实支持 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 Haswell
和 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
请注意,无论是否使用 CPU
指令,它 assemble extern ymm0
都很好,但是一旦将其用作操作数,就会出现问题。
NASM 允许您在符号前加上美元符号 $
,以便它被解释为符号而不是寄存器或其他保留字。来自 NASM documentation:
3.1 Layout of a NASM Source Line
[...] An identifier may also be prefixed with a
$
to indicate that it is intended to be read as an identifier and not a reserved word; thus, if some other module you are linking with defines a symbol calledeax
, you can refer to$eax
in NASM code to distinguish the symbol from the register. [...]
MASM 通常仅用于 C 编译器使用下划线作为标识符前缀的环境 _
,因此对于该汇编器来说这不是什么大问题。然而它确实有解决这个问题的方法,但它基本上与 NASM 的相反。您可以使用 OPTION NOKEYWORD 指令来禁用您选择的保留字。例如,您可以使用 OPTION NOKEYWORD:<eax>
,这样您就可以使用名为 eax
的符号。当然,这会阻止您使用名为 EAX 的寄存器,因此它不像 NASM 那样通用。