简体   繁体   English

符号名称与新NASM版本中的新注册名称冲突?

[英]Symbol name conflicts with new register names in new NASM versions?

Imagine you wrote this 10 years ago (before Intel MPX and the bnd0 .. bnd3 registers were even on a roadmap): 想象一下你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

How can you assemble this with a current version of NASM? 如何使用当前版本的NASM进行组装? ie Does NASM (or YASM) have forward compatibility with new versions that support new register names? 即NASM(或YASM)是否与支持新注册名称的新版本具有向前兼容性?

Obviously this is easy to solve with search/replace inside a single file or project. 显然,在单个文件或项目中搜索/替换很容易解决。 But in theory, you could have a global variable name as part of a library ABI that you either export from NASM or need to import into NASM with extern ymm0 . 但理论上,您可以将全局变量名称作为库ABI的一部分,您可以从NASM导出或需要导入带有extern ymm0 NASM。 (External symbols have to be declared, so unrecognized register names never assemble to symbol references.) (必须声明外部符号,因此无法识别的寄存器名称永远不会汇编为符号引用。)

NASM syntax is already unsuitable as a format for C compiler output on platforms which don't prefix symbol names with an _ or do some other kind of name mangling (eg Linux ELF). NASM语法已经不适合作为平台上C编译器输出的格式,这些平台不使用_前缀符号名称或者执行其他类型的名称修改(例如Linux ELF)。 You can't compile a global int eax = 1; 你无法编译全局int eax = 1; . This is why AT&T syntax uses %eax for register names . 这就是为什么AT&T语法使用%eax作为寄存器名称的原因 Discussion in comments on that answer is what inspired this question. 对该答案的评论中的讨论是启发这个问题的原因。 Note that GAS doesn't need external symbols to be declared; 请注意,GAS不需要声明外部符号; unrecognized names are treated as symbols (even in .intel_syntax noprefix mode which uses a syntax similar to MASM). 无法识别的名称被视为符号(即使在.intel_syntax noprefix模式中,它使用类似于MASM的语法)。

Related: how does MASM handle forward source compatibility for new extensions? 相关:MASM如何处理新扩展的前向源兼容性?


Can you disable MPX support somehow? 你能以某种方式禁用MPX支持吗?

YASM supports a CPU directive that lets you disable support for some mnemonics, but even disabling AVX support doesn't let you use ymm0 as a symbol name. YASM支持CPU指令 ,允许您禁用对某些助记符的支持,但即使禁用AVX支持也不允许您使用ymm0作为符号名称。 (YASM 1.3.0 doesn't support AVX512 or MPX, so it can assemble code that uses those register names as symbols, but it does support AVX2.) (YASM 1.3.0不支持AVX512或MPX,因此它可以汇编使用这些寄存器名称作为符号的代码,但它确实支持AVX2。)

CPU Conroe
extern ymm0

I get yasm-CPU.asm:2: error: directive 'extern' requires an identifier parameter . 我得到yasm-CPU.asm:2: error: directive 'extern' requires an identifier parameter Or with ymm0: dd 123 , the error is yasm-CPU.asm:2: error: label or instruction expected at start of line 或者使用ymm0: dd 123 ,错误是yasm-CPU.asm:2: error: label or instruction expected at start of line

But AVX support is definitely disabled: assembling CPU Conroe / vmovaps xmm0, [edi] gives: 但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    

(It says CPU 686 or similar for older disabled extensions. IDK why it doesn't say in CPU Sandybridge AVX . It seems that yasm is no longer well maintained. YASM 1.3.0 supports CPU Haswell and AVX2 , but the docs don't mention it.) (它表示CPU 686或类似的旧版禁用扩展in CPU Sandybridge AVX为什么它没有in CPU Sandybridge AVX说。似乎yasm不再保持良好in CPU Sandybridge AVX 1.3.0支持CPU HaswellAVX2 ,但文档不提到它。)

The intent of this feature is to stop you from accidentally using SSE4 instructions in a function for SSSE3-or-lower CPUs, but apparently it doesn't help with this problem. 此功能的目的是阻止您在SSSE3或更低CPU的函数中意外使用SSE4指令,但显然它无法解决此问题。


NASM's CPU directive seems to be similar, and also doesn't help at all: 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

Note that it does assemble extern ymm0 just fine, with or without a CPU directive, but as soon as you use it as an operand, you have a problem. 请注意,它确实组装了extern ymm0 ,无论是否有CPU指令,但只要将其用作操作数,就会出现问题。

NASM lets you prefix a symbol with a dollar sign $ so that it's interpreted as symbol rather than register or other reserved word. NASM允许您在符号前面添加美元符号$以便将其解释为符号而不是寄存器或其他保留字。 From the NASM documentation : 来自NASM文档

3.1 Layout of a NASM Source Line 3.1 NASM源线的布局

[...] 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. 因此,如果您链​​接的某个其他模块定义了一个名为eax的符号,您可以在NASM代码中引用$eax来区分符号和寄存器。 [...] [...]

MASM is normally only used in environments where C compilers prefix identifiers with underscores _ , so this isn't as big of an issue with that assembler. MASM通常仅用于C编译器使用下划线_作为前缀标识符的环境中,因此这不是该汇编程序的大问题。 However it does have a solution this problem, but it's basically the opposite of NASM's. 然而它确实解决了这个问题,但它基本上与NASM相反。 You can use the OPTION NOKEYWORD directive to disable reserved words of your choice. 您可以使用OPTION NOKEYWORD指令禁用您选择的保留字。 For example you can use OPTION NOKEYWORD:<eax> so that you can use a symbol named eax . 例如,您可以使用OPTION NOKEYWORD:<eax>以便您可以使用名为eax的符号。 Of course that prevents you from using the register named EAX, so it's not as general solution as NASM's. 当然,这会阻止您使用名为EAX的寄存器,因此它不像NASM那样通用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM