GCC manual says that -m32
"generates code that runs on any i386 system". Assume I want to write a function that swaps the bytes of a 32 bit number:
.text
.globl SwapBytes
.type SwapBytes, @function
SwapBytes:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %eax
bswapl %eax
popl %ebp
ret
However, the BSWAP
instruction is not supported on 80386, only since 80486. So I assemble gcc SwapBytes.s -march=i486 -c -o SwapBytes.elf
, as suggested by the cited manual. But then I get an error:
Assembler messages:
Error: invalid instruction suffix for `push'
Error: invalid instruction suffix for `pop'
But why? I thought, 32 bit stack was introduced with 80386. Ok, let's try with -march=pentium3
in case I missed something about 32 bit stack, but the same result. However, if I assemble just with the -m32
option, gcc
does not complain.
I thought maybe gcc
ignores the -march=...
options when assembling (and assumes -m64
?), but does not ignore the -m32
option? But what options can I use to specify the CPU I want to assemble for?
It appears that gcc passes the -m32
and -m64
options to the assembler (translating them to --32
and --64
), but it does not pass along the -march=
options. I think this is because the assembler recognizes a different set of architectures than the compiler does. For instance, -march=skylake
is accepted by gcc but would be an error to the assembler.
But you can pass it explicitly using the -Wa
option. So for instance gcc -m32 -Wa,-march=i386 bswap.s
will give
Error: `bswap' is not supported on `i386'
and gcc -m32 -Wa,-march=i486 bswap.s
will run successfully.
Note that the default architecture depends on how you configured your binutils installation. But it is most likely something much more modern than i386
, which is why the assembler doesn't complain when you use bswap
without an -march
option.