问题描述
我正在使用nasm 2.14.02在Ubuntu上。
我正在尝试通过将变量压入堆栈然后调用printf来使用nasm编写一个简单的hello world程序:
; Import c-lib printf
extern printf
; Define Message and Length
section .data:
msg: db "Hello People!",0xA
msg_len equ $-msg
section .text:
global _start
_start:
push msg
call printf
mov eax,1
mov ebx,0
int 80h
使用nasm组装程序可以正常工作,但是当我尝试将其与ld链接时,会引发以下错误:
ld: hello_world.o: in function `_start':
hello_world.asm:(.text:+0x6): undefined reference to `printf'
因此,似乎extern不会导入printf。我究竟做错了什么。从字面上看,这是我的第一个汇编程序,所以请使用简单的单词。
编辑:
我正在使用的命令是:
nasm hello_world.asm -f elf64
ld hello_world.o -o hello_world
解决方法
您需要将您的代码与提供 printf
的库相关联;这是由 C 标准库提供的。获得它的最简单方法是使用 gcc 为您调用链接器。
nasm -felf32 hello_world.asm
gcc -static -o hello_world hello_world.o
上面的将不起作用,但是,因为 gcc 将尝试添加一些在 crt1.o
中找到的额外代码,其中包含 _start
以启动 C 运行时,然后调用 { {1}}。
对您的代码进行最简单的修复是改为编写 main
方法。
main
我不是在 32 位机器上,所以我无法轻松测试,但我认为这正是您所需要的。使用 section .text:
global main
main:
push ebp ; these two lines are the usual function entry
mov ebp,esp
push msg
call printf
xor eax,eax ; set eax to zero as the return value
mov esp,ebp ; these two lines are the usual function exit
pop ebp
ret
然后使用 nasm
,如上,组装和链接它。
如果您确实想使用 gcc
,那很好。您需要链接 C 标准库(静态地......使用 GOT 是另一回事),可能使用 _start
。