I have tested a bit of assembler on Linux using the AT&T syntax.开发者_运维知识库 One thing that struck me was that the book I was reading was written from a 32-bit standpoint. Thus, all sizes would have to be changed to the correct 64-bit versions for me. Or I could (which I did) assemble the code using the --32 flag for as and the -melf_i386 flag for ld when linking. I have also adapted some of the code and to run on Windows under Cygwin.
But that got me thinking. Is there a way to do ifdef like checks in assembler to do one thing if I'm on Windows and another under Linux and also handle 32 vs 64 bit that way? For example to have a .globl _start under Linux and a .globl _main under Windows.
Or is this handled by checking before assembling and having different source files to assemble based on the result of the checks?
I.e. foo_linux.s and foo_windows.s
If so, how do you overcome that fact that you will not know which .s files you will use, and thus have to include, when you are creating your program?
For example, say that we have a socket_linux.s and a socket_windows.s. They both present an identical interface but do the OS specific work associated to sockets. But when I work with the sockets in my program I will not know if I need the Windows or Linux version included. So I would be kinda screwed :)
So how is this handled in Assembler? In C++ for example I could include my socket.h and socket.cpp and wrap all the Linux and Windows specific code in #ifdef statements.
If you use GCC to compile your files and name them .S
(with uppercase S) or .sx
, it will pass them through the preprocessor before invoking the assembler.
From the docs:
file.s
Assembler code.
file.S
file.sx
Assembler code which must be preprocessed.
You can add -v
to the command line to see how the various sub-processes are invoked.
in MASM (.asm), you can use ifdef
, ifndef
and the likes, as:
ifdef X64
endif
When writing for different platforms you can define some macro for loading target specific files:
FILE target.h
#if defined(__arm__)
#define target "arm"
#elif defined(__x86_64__)
#if defined(_WIN64)
#define target "win64"
#else
#define target "linux64" // all non-Win share the same calling convention
#endif
#else
// 32bit defs
#endif
Then you can include target specific files with the macro, two string literals successively get one single literal:
#include "target.h"
#include "target_specific_code_" target ".h"
It includes one of these files:
target_specific_code_arm.h
target_specific_code_win64.h
target_specific_code_linux64.h
...
EDIT:
Like this, you can also define target specific assembler instructions for later use in inline assembly:
#ifdef ...
#define ASM_PP_LOAD_WORD "movi "
#else
#define ASM_PP_LOAD_WORD "mov "
#endif
or as macro
#ifdef ...
// when using intel assembler there is a different
// order of parameters
#define ASM_PP_LOAD_WORD(a, b) "movi " #b ", " #a
#else
#define ASM_PP_LOAD_WORD(a, b) "mov " #a ", " #b
#endif
精彩评论