So I'm new trying asm and I want to compile a little program that just exits with i386 instructions instead of x86-64 ones. I have a x86-64 Ubuntu which compile and run x86-64 one perfectly but I don't get it how to assemble and link the i386 version on the same x86-64 machine (I have installed i386 compat).
I know there are similar questions answered already, But none of them use as
and ld
to do it so I don't know exactly how could I translate those solutions to my problem.
For the x86-64 I use as
and ld
as follows:
# Assemble: as exit.s -o exit.o
# Linking: ld exit.o -o exit
The x86-32 version of the program:
.section .data
.section .text
.globl _start
_start:
movl $1, %eax
movl $0, %ebx
int $0x80
Now.. I've been searching how to do it and found about the --32
in as and the -m {arg}
in ld
but every time I get to compile it without arch errors it gives me the "File in wrong format" error.
I've tried doing ld with elf_i386 and i386linux like this:
as --32 exit.s -o exit.o
ld -m elf_i386 exit.o -o exit
#Error: -bash: ./exit: cannot execute binary file: File in wrong format
ld -m i386linux exit.o -o exit
#Error: -bash: ./exit: cannot execute binary file: File in wrong format
I want to add that for compatibility I've installed these packages listed in the Ubuntu help forum:
sudo dpkg --add-architecture i386
sudo apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386
sudo apt-get install multiarch-support
Those are the correct commands for assembling and linking a 32-bit static executable. (Assembling 32-bit binaries on a 64-bit system (GNU toolchain))
Looks like your kernel was built without CONFIG_COMPAT_BINFMT_ELF
List of executable formats on Linux, so it doesn't recognize 32-bit ELF static executables as executable. (I think that's the relevant Linux kernel config option.)
Or you're using the Windows Subsystem version 1 for Linux, which also doesn't support 32-bit executable.
WSL v1 doesn't support the 32-bit int 0x80
ABI from 64-bit processes, either, so that also won't work. (What happens if you use the 32-bit int 0x80 Linux ABI in 64-bit code?). It's like a Linux kernel without CONFIG_IA32_EMULATION
.
See Does WSL 2 really support 32 bit program? for how to make sure you're really using WSL2, which is a real Linux kernel in a VM, and thus allows 32-bit user-space.
libc packages are irrelevant for this. You're making a static executable which doesn't depend on any other files to run.
After running your build commands on my Arch Linux system, I get:
$ as --32 exit.s -o exit.o
$ ld -m elf_i386 exit.o -o exit
$ file exit
exit: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, not stripped
$ ./exit ; echo $?
0
So it works fine, your system is just broken somehow. It's either not real Ubuntu, or you have a custom kernel.