前面的汇编代码没有使用libc库函数,都是通过直接进行系统调用完成。《32位汇编语言学习笔记(21)--用NASM实现Hello World小程序》通过系统调用实现了一个HelloWorld小程序,我们要通过在汇编中调用libc函数实现一个新版本的HelloWorld小程序:
SECTION .data ; Section containing initialised data
HelloMsg: db "Hello World!",0
SECTION .bss ; Section containing uninitialized data
SECTION .text ; Section containing code
extern puts ; Simple "put string" routine from clib
global main ; Required so linker can find entry point
main:
push ebp ; Set up stack frame for debugger
mov ebp,esp
push ebx ; Must preserve ebp, ebx, esi, & edi
push esi
push edi
push HelloMsg
call puts ; Call clib function for displaying strings
add esp,4 ; Clean stack by adjusting ESP back 4 bytes
pop edi ; Restore saved registers
pop esi
pop ebx
mov esp,ebp ; Destroy stack frame before returning
pop ebp
ret ; Return control to Linux
注意入口,已经从_start改成了main,另外,为了使用puts函数,添加了语句extern puts。
在main函数中,调用puts之前,需要把入参压入到堆栈:push HelloMsg,HelloMsg,需要以0结尾。
为了维护堆栈平衡,在call指令后,add esp,4,用于清除压入的HelloMsg参数。
下图描述了我们编写的汇编代码和libc库的交互过程:
makefile文件内容:
helloclib: helloclib.o
gcc -o helloclib helloclib.o
helloclib.o: helloclib.asm
nasm -f elf32 -g -F stabs helloclib.asm -l helloclib.lst
注意,在链接时不是使用ld,而是使用gcc。
测试:
[root@bogon helloclib]# make
nasm -f elf32 -g -F stabs helloclib.asm -l helloclib.lst
gcc -o helloclib helloclib.o
[root@bogon helloclib]# ./helloclib
Hello World!