在Windows上的64位Ubuntu上编译32位汇编代码

4
编辑:看起来问题是Windows子系统无法处理32位。
我是一个汇编和Linux新手,正在尝试在Windows上的64位Ubuntu上编译32位汇编(AT&T语法)。我的情况几乎与此其他stackoverflow问题完全相同,但那里的解决方案(我在许多其他帖子中看到重复)对我不起作用,原因不明。我正在学习《从底层开始编程》这本书中的x86汇编,但我无法在Windows上的Bash on Ubuntu上编译程序。
我尝试了多种命令选项的组合,有些似乎可以编译,但我要么无法执行二进制文件(格式错误),要么可以执行但在源文件的movl 8(%ebp), %eax处出现分段错误(我读到这可能是由于在64位环境中设置32位堆栈导致的)。
没有.32code作为我的程序的第一行,使用as--32选项时,没有任何有用的尝试:没有.32code和有--32(不能嵌入图像在我的帖子中所以放链接)。
仍然没有.32code,现在使用了--x32没有.32code和有--x32),我发现如果不包括.32code,它会出现推送、弹出等问题。因此,在我的源文件中包含它:有.32code和有--x32
然后,我可以尝试使用gcc而不是asld进行类似的尝试,但我不确定是否有意义包括所有不同的失败组合并打开那个罐子,因为这样我们就会涉及到gcc是否具有所需的库(?)。例如,使用gcc -m32 -nostdlib factorial.s -o factorial,我得到“无法执行二进制文件:执行格式错误”的消息,无论是否有.32code。尝试诸如sudo apt-get install lib32gcc-4.8-dev和其他尝试,没有什么能够工作,很多时候我遇到了关于qemu-user-static的问题,可能是因为我曾经安装过它,现在它都乱了。

有一个答案建议只安装32位gcc,但这对我似乎没有任何作用。另一个解决方案可能是将书中的所有示例手动转换为64位,并忘记所有这些。我想这意味着重新构想堆栈以包含8个而不是4个(即像4(%esp)这样的东西将变成8(%esp)),但也可能会更改一些movlmovq,例如,或一些%eax%rax等。但我觉得应该有一些解决方法,特别是2013年张贴者似乎已经解决了确切的问题。也许我需要尝试使用像-march=CPU[+EXTENSION...]-mtune=CPU之类的东西?也许我只是缺乏关于架构、Linux或as/gcc的基本知识?


使用ld -melf_i386是正确的仿真方式。 - Jester
@Jester谢谢你的提示,但是我考虑到这种仿真,我尝试在我的.s文件中使用.32code,但是as --32as --x32都不起作用。然后,删除.32code并重试这两个as选项也不起作用:点击这里 - Jaime Salazar
1
你得到了正确的32位二进制输出。现在需要找出为什么你的Ubuntu无法运行它。你使用WSL吗?显然,它根本不支持32位(请参见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
@Jester,糟糕,这可能一直是问题所在吗?那个链接似乎暗示着Windows的Linux子系统无法处理32位。我想现在我可能需要在虚拟机上安装Ubuntu了... - Jaime Salazar
要从汇编源代码(带/不带libc或CRT启动文件)构建32位二进制文件,请参见https://dev59.com/ZFoU5IYBdhLWcg3w_KmO。如果您只定义“_start:”,则`gcc -m32 -static -nostdlib foo.S`应该可以工作。 - Peter Cordes
如果你刚开始学习汇编语言,不要试图将示例移植到64位。调用约定是不同的,这肯定会让你的生活更加困难。找一本带有64位示例的书或指南。 - Peter Cordes
1个回答

1
我认为您的汇编程序运行良好。如果您想链接到已安装的glibc版本,需要确保安装了i386版本的开发包(可能是libc6-dev:i386,但根据发行版版本也可能是libc6-dev-i386),并使用gcc -m32进行链接以获取正确的路径。然后,gcc编译器驱动程序将使用适当的标志调用ld
您可以通过使用gcc -m32编译和链接一个小的C文件来验证您是否拥有可工作的设置。这应该会生成一个32位程序。

感谢您的提示,这可能有助于我诊断问题。您可以在此图片中看到,最新版本的libc6-dev:i386libc6-dev-i386gcc-multilib已经安装,并且我的gcc版本是x86_64。因此,使用这个C语言示例,它会警告我关于32位编译(是糟糕的C程序还是糟糕的32位gcc?),但是对于64位编译没有任何问题。这是因为我的gcc是x86_64吗? - Jaime Salazar
1
@JaimeSalazar :你是在Windows子系统中运行这段代码吗(适用于Windows 10的Ubuntu)? - Michael Petch
@JaimeSalazar 看起来WSL无法执行32位二进制文件。 - fuz
@fuz 是的,多亏了Jester,我几分钟前就发现了 -.- 谢谢大家,我会更新我的问题。 - Jaime Salazar
1
@JaimeSalazar 请将这些知识作为答案发布,以便那些偶然遇到您的问题的人能够快速找到它。 - fuz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接