4

EDIT: It's looking like the issue is that the Windows Subsystem for Linux can't deal with 32-bit.

Assembly and linux newbie here trying to compile 32-bit assembly (AT&T syntax) on 64-bit Ubuntu on Windows. My situation is practically an exact replica of this other stackoverflow question but the solutions there (which I see repeated in many other posts) does not work for me, for some reason. I am learning x86 assembly with the book Programming from the Ground Up and I can't get the programs to compile on Bash on Ubuntu on Windows.

I've tried multiple combinations of options in my commands, some manage to apparently compile, but I either can't execute the binary file (format error) or I can but I get a segmentation fault when I get to movl 8(%ebp), %eax in my source file (I read that it's probably due to setting up a 32-bit stack in a 64-bit environment).

Without .32code as the first line of my program and with a --32 option for as, no attempts with ld produce anything helpful: without .32code and with --32 (can't embed images in my posts yet so putting link instead).

Still without .32code and now with --x32 (without .32code and with --x32) I found out it has trouble with push, pop, etc. if you don't include the .32code so here I include it in my source file: with .32code and with --x32.

Then, there are similar attempts I can make with gcc instead of as and ld but I'm not sure if it makes sense to include all the different combinations of failures and open up that can of worms because then we get into whether gcc has the libraries it needs (?). For example, with gcc -m32 -nostdlib factorial.s -o factorial I get the "cannot execute the binary file: Exec format error" message, with or without the .32code. Trying things such as sudo apt-get install lib32gcc-4.8-dev and other attempts, nothing seems to work and a lot of times I get issues with qemu-user-static maybe because I at one point installed it and now it's all f%^#!d.

One answer recommended just installing 32-bit gcc but that didn't seem to do anything for me. Another solution could be to manually convert all the examples in the book to 64-bit and forget about all of this. I imagine that would imply re-envisioning the stack to contain of 8 instead of 4 (ie. things like 4(%esp) would become 8(%esp)) but also maybe change some movl to movq, for example, or some %eax to %rax, etc. But I feel there should be some solution to this, especially how the poster in 2013 seemed to have the exact issue solved. Maybe I need to try again with stuff like -march=CPU[+EXTENSION...] or -mtune=CPU? Maybe I'm just lacking basic knowledge on architectures, or linux, or as/gcc?

Jaime Salazar
  • 349
  • 1
  • 2
  • 11
  • `ld -melf_i386` is the correct emulation to use. – Jester Nov 19 '17 at 15:43
  • @Jester thanks for the tip but with that emulation in mind, I've tried with `.32code` in my .s file and neither `as --32` nor `as --x32` seem to work. Then, taking out the `.32code` and retrying the two `as` options doesn't work either: [see here](https://i.imgur.com/4RuTXRX.png) – Jaime Salazar Nov 19 '17 at 16:14
  • 1
    You got the correct 32 bit binary output. Now to figure out why your ubuntu won't run it. Are you using WSL? Apparently that simply [doesn't support 32 bit](https://wpdev.uservoice.com/forums/266908-command-prompt-console-bash-on-ubuntu-on-windo/suggestions/13377507-please-add-32-bit-elf-support-to-the-kernel). – Jester Nov 19 '17 at 16:18
  • @Jester, crap, could that have been the issue all along? That link seems to imply that the Linux Subsystem for Windows seems incapable of dealing with 32-bit. I'm thinking I might need to install Ubuntu on a VM now... – Jaime Salazar Nov 19 '17 at 16:50
  • For building 32-bit binaries from asm source (with / without libc or CRT start files), see https://stackoverflow.com/questions/36861903/assembling-32-bit-binaries-on-a-64-bit-system-gnu-toolchain. `gcc -m32 -static -nostdlib foo.S` should work if you just define `_start:`. – Peter Cordes Nov 19 '17 at 22:22
  • If you're just learning asm, don't try to port the examples to 64-bit. The calling convention is different, and you will definitely be making life harder. Find book or guide with 64-bit examples. – Peter Cordes Nov 19 '17 at 22:24

1 Answers1

1

I think your assembler is just working fine. If you want to link against the installed glibc version, you need to make sure to install the i386 version of the development packages (likely libc6-dev:i386, but it could also be libc6-dev-i386 depending on the distribution version), and link with gcc -m32 to get the right paths. The gcc compiler driver will then invoke ld for you with the appropriate flags.

You can verify that you have a working setup by compiling and linking a small C file with gcc -m32. This should generate a 32-bit program.

Florian Weimer
  • 32,022
  • 3
  • 48
  • 92
  • Thanks for the tips, this might be getting me somewhere as far as diagnosing the problem. You'll see in [the image](https://i.imgur.com/QvHSCEn.png) that the newest versions of `libc6-dev:i386`, `libc6-dev-i386`, and `gcc-multilib` are already installed and that my gcc version is x86_64 I think. So using [this C example](http://www.geeksforgeeks.org/compile-32-bit-program-64-bit-gcc-c-c/), it warns me about the 32-bit compilation (bad C program or bad 32-but gcc?) but it has no issues with the 64-but compilation. Is it because my gcc is x86_64? – Jaime Salazar Nov 19 '17 at 16:44
  • 1
    @JaimeSalazar : Are you running this code in the Windows Subsystem for Linux (The Ubuntu available for Windows 10)? – Michael Petch Nov 19 '17 at 17:37
  • @JaimeSalazar It appears that WSL cannot execute 32 bit binaries. – fuz Nov 19 '17 at 17:51
  • @fuz Yep, thanks to Jester I found out a couple of minutes ago -.- thanks guys, will update my question – Jaime Salazar Nov 19 '17 at 18:01
  • 1
    @JaimeSalazar Please post this knowledge as an answer so people who stumble upon your question quickly find it. – fuz Nov 20 '17 at 11:04