【问题标题】:Symbol name conflicts with new register names in new NASM versions?符号名称与新 NASM 版本中的新寄存器名称冲突?
【发布时间】:2018-02-04 01:11:37
【问题描述】:

想象一下,你在 10 年前写了这篇文章(在 Intel 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。 (必须声明外部符号,因此无法识别的寄存器名称永远不会汇编为符号引用。)

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

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


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

YASM supports a CPU directive 允许您禁用对某些助记符的支持,但即使禁用 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 HaswellAVX2,但文档没有提到它。)

此功能的目的是防止您在用于 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 指令,它都可以很好地组装extern ymm0,但是一旦将它用作操作数,就会出现问题。

【问题讨论】:

  • 旁注:显然即使gcc 也无法为int eax=1-masm=intel 生成有效代码。也许他们应该使用.intel_syntax prefix。人们一直在抨击&t......他们只是不了解优势! :)
  • 请注意,在引入 ELF 之前,UNIX 汇编程序没有在 x86 上使用 % 前缀,因为每个符号都带有下划线前缀。
  • @Jester 我理解优势,我抨击 AT&T 因为它对计算机比对人类更好。这篇文章只是强制执行该观点。 :) (问题中的问题是假设性的,当我试图让我的旧 TASM 时代介绍工作时,我只是手动修补它们,你通常只有几行 ASM 源代码可以使用,否则你有比 NASM 版本更大的问题)

标签: assembly x86 nasm naming forward-compatibility


【解决方案1】:

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

3.1 NASM 源代码行的布局

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

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

【讨论】:

  • 酷。这可能仍然需要全局搜索/替换以在您的 asm 源中将 k0 替换为 $k0,但这种痛苦类似于其他语言引入新关键字时。难怪CPU 指令没有做任何事情,因为问题已经以不同的方式解决了。我想当我试图用谷歌搜索答案时,我使用的是label 而不是symbol
猜你喜欢
  • 2018-01-13
  • 2020-06-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-15
相关资源
最近更新 更多