How to detect architecture in NASM at compile time

2019-02-22 20:33发布

问题:

I am looking for some preprocessor functionality in nasm that would allow having one source code for both x86 and x64 architectures.

I mean something in the vein of ifdef some_constant. Like C preprocessor uses if it wants to detect say if it's compiled on Windows or Linux.

Edit

I know about nasm flags. I use them. I just want to have the very same source code and expect preprocessor to handle it correctly based on those flags. I'd use ifdef ... else for stack operations and so one, having the core code same for both architectures.

回答1:

NASM cannot detect the architecture, but you can use the output format (command line option: -felf,-felf32,-felf64,-fwin32 etc.) for your needs. Read the Friendly Manual.



回答2:

In the NASMX package you can find the %if BITS == 64 line in syscalls.inc. This determine wether you are using nasm 64 bits or 32 bits. Perhaps this is what you wanna know?



回答3:

__OUTPUT_FORMAT__

http://www.nasm.us/doc/nasmdoc4.html#section-4.12.6

The __OUTPUT_FORMAT__ standard macro holds the current Output Format, as given by the -f option or NASM's default. Type nasm -hf for a list.

%ifidn __OUTPUT_FORMAT__, win32 
  %define NEWLINE 13, 10 
%elifidn __OUTPUT_FORMAT__, elf32 
 %define NEWLINE 10 
%endif


回答4:

NASM allows you to freely change the code size (using the bits directive) anywhere you like, which allows you to have 16-bit or 32-bit code in an elf64, or 64-bit code in an elf32. For this reason detecting the output format is relatively wrong (fragile).

Instead you want to detect the current code size. For this purpose NASM has a standard macro called __BITS__. This means you can do %if __BITS__ = 64.

However, 32-bit code and 64-bit code typically use completely different calling conventions; and 64-bit code has more registers, wider registers and other differences (where not using the extra registers or the extra width means that the code would be extremely poor quality - far worse than compiler generated code). This means that (excluding only using it for a few small macros) attempting to support both 32-bit and 64-bit in the same code is extremely silly. You just end up with completely different code for completely different cases that are slapped into the same file for no sane reason and then separated (using preprocessor magic) to work-around the fact that it never made sense in the first place.

More sensible is to have separate files for separate cases (e.g. a src/arch/x86_32 directory and a src/arch/x86_64 directory), and in that case you can just let the build script or makefile sort it out (e.g. tell the assembler to use a different "include path").