在64位ubuntu上编译32位汇编程序

15

我有一个用32位汇编语言写的程序... 现在我无法在64位操作系统上编译它。我们学校要求程序必须是32位版本。这是我的程序:

bits 32
extern _printf
global _start

section .data
    message db "Hello world!!", 10, 0

section .text

_start:
    pushad 
    push dword message
    call _printf 
    add esp, 4 
    popad 
    ret

有什么想法吗?我已经尝试了很多编译方法。编译后的错误输出:

nasm -f elf64 vaja4.asm
ld vaja4.o -o vaja4
./vaja4

输出:

vaja4.o: In function `_start':
vaja4.asm:(.text+0x7): undefined reference to `_printf'

那不应该是 printf 而不是 _printf 吗? - iabdalkader
同样的错误:vaja4.o: 在函数 start' 中: vaja4.asm:(.text+0x7):对 printf' 的引用未定义。 - Klemenko
4个回答

24

首先将_printf更改为printf,将_start符号更改为main,然后使用gcc链接目标文件,它会自动将其链接到libc你需要这样做是因为据我所知,在没有main的情况下无法链接到libc。此外,在组装时应使用elf32而不是elf64,因为代码具有32位指令:

bits 32
extern printf
global main

section .data
    message db "Hello world!!", 10, 0

section .text

main:
    pushad 
    push dword message
    call printf 
    add esp, 4 
    popad 
    ret

使用以下工具进行构建:

nasm -f elf32 vaja4.asm
gcc -m32 vaja4.o -o vaja4
$./test 
$Hello world!!

编辑:

由于您现在正在64位系统上编译32位代码,因此您需要安装库的32位版本。

apt-get install ia32-libs 

1
是的,这是正确的方法。如果您想使用libc,则应将main用作入口点,并使用gcc进行链接,以便拉取适当的libc部件并处理初始化/关闭。此外,仅返回值仅适用于main,如果您创建没有libc的二进制文件,则必须使用退出系统调用。 - Jester
好的,我尝试了你的方法。在执行gcc -m32 vaja4.o -o vaja4后,它输出以下错误:http://pastebin.com/jX3N2GSJ - Klemenko
你需要安装32位库,使用apt-get install ia32-libs命令。 - iabdalkader
1
我尝试安装那些库,但仍然出现相同的错误。现在我安装了libc6-dev-i386库,它可以工作了!谢谢 :) - Klemenko
你可以从仅定义“_start”的程序中链接libc。但是,如果您制作静态二进制文件,则必须调用glibc的init函数,或者使用像musl这样不需要init函数的libc。(在Linux上进行动态链接会在“_start”之前调用glibc的init函数)。请参阅我在我标记为重复的问题上的答案。(“_printf”与“printf”的问题是单独的,但除此之外,它们正在询问同样的事情) - Peter Cordes

9
在Ubuntu 12.10上,您需要首先安装开发包。
sudo apt-get update
sudo apt-get install libc6-dev-i386

for

gcc -m32 vaja4.o -o vaja4

工作。


4

我怀疑你所看到的错误不是由32位/64位问题引起的。你所看到的错误是

与此相关的。
vaja4.asm:(.text+0x7): undefined reference to `_printf'

很明显告诉你符号_printf未定义,这意味着printf函数的库没有被链接。
您的链接步骤,即:
ld vaja4.o -o vaja4

不包含任何库文件。你需要链接一个能够提供printf函数定义的库文件到你的程序中。我相信ld应该自动选择合适的库文件而无需打扰你,但因为它找不到适合这个函数的C库文件,所以我猜你缺少所需的库文件,即32位或64位库文件中的一个。

无论如何,请尝试以下命令序列来汇编和链接你的程序:

nasm -f elf vaja4.asm
ld -m elf_i386 vaja4.o vaja4
./vaja4

甚至ld -m elf_i386 -I/lib/ld-linux.so.2 -lc vaja4.o -o vaja4可能不需要-I开关-肯定需要-lc和输出文件名的-o_start标签被跳转而不是调用,所以你不能从中返回ret。使用main和gcc更容易... - Frank Kotler

1

在我看来,你好像忘记链接C库了,这是提供printf函数(和其他函数)的部分:

ld vaja4.o -o vaja4 -lc

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