Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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):

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? i.e. Does NASM (or YASM) have forward compatibility with new versions that support new register names?

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. (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 (e.g. Linux ELF). You can't compile a global int eax = 1;. This is why AT&T syntax uses %eax for register names. Discussion in comments on that answer is what inspired this question. Note that GAS doesn't need external symbols to be declared; unrecognized names are treated as symbols (even in .intel_syntax noprefix mode which uses a syntax similar to MASM).

Related: how does MASM handle forward source compatibility for new extensions?


Can you disable MPX support somehow?

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 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.)

CPU Conroe
extern ymm0

I get 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

But AVX support is definitely disabled: assembling CPU Conroe / vmovaps xmm0, [edi] gives:

$ 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.)

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.


NASM's CPU directive seems to be similar, and also doesn't help at all:

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.

like image 624
Peter Cordes Avatar asked Aug 25 '17 23:08

Peter Cordes


1 Answers

NASM lets you prefix a symbol with a dollar sign $ so that it's interpreted as symbol rather than register or other reserved word. From the 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 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. However it does have a solution this problem, but it's basically the opposite of NASM's. You can use the OPTION NOKEYWORD directive to disable reserved words of your choice. For example you can use OPTION NOKEYWORD:<eax> so that you can use a symbol named eax. Of course that prevents you from using the register named EAX, so it's not as general solution as NASM's.

like image 121
Ross Ridge Avatar answered Oct 22 '22 16:10

Ross Ridge