5、Linux汇编——动态链接库

1、使用动态链接库

 (1)不调用库函数

 下面的程序不使用动态库,直接将hello world 输出到屏幕上并退出。源代码存放在文件helloworld-nolib.s中。

.include "linux.s"
.section .data
    helloworld:    .ascii "hello world\n"
    helloworld_end:
    .equ helloworld_len, helloworld_end - helloworld
 
.section .text
.globl _start
    _start:    movl $STDOUT, %ebx
               movl $SYS_WRITE, %eax
               movl $helloworld, %ecx
               movl $helloworld_len, %edx
               int $LINUX_SYSCALL
               
               movl $0, %ebx
               movl $1, %eax
               int $LINUX_SYSCALL

编译、链接、执行该函数

as helloworld-nolib.s -o helloworld-nolib.o

ld hellowordl-nolib.o -o helloworld-nolib

(2)调用库函数

下面程序将调用C库中的printf函数和exit函数。功能还是打印hello world,并退出程序。源代码保存在helloworld-lib.s文件中。

.section .data
    helloworld:    .ascii "hello world\n"

.section .text
    .globl _start
    _start:    pushl $helloworld
               call printf
               
               pushl $0
               call exit

编译、链接、执行上面程序:

as helloworld-lib.s -o helloworld-lib.o

ld -dynamic-linker /lib/ld-linux.so.2 -o helloworld-lib helloworld-lib.c -lc

说明:(1)ld-linux.so.2文件是动态库载入有关的文件,其主要作用是指导目标文件如何载入动态库。其为glibc的库文件。

(2)-lc表示连接到c库,该库在系统上的文件名为libc.so,动态库的一般格式为:lib + 库名 + .so

(3)程序执行步骤:a、加载文件/lib/ld-linux.so.2,这个为动态链接器,其会查看helloworld程序,并连接C库

                                链接器会在标准目录:/etc/ld.so.conf和环境变量LD_LIBRARY_PATH中的目录下查找名为libc.so的库。

                                b、在库中查找printf和exit函数

                                c、调用被调函数

(4)下面命令查看执行文件所依赖的库文件:ldd  ./helloworld-nolib

                                                                     ldd ./helloworld-lib

(3)调用printf函数

printf函数将返回的打印出来的整数返回到%eax中。存入文件printf-example.s中

#目的:演示调用printf函数
.section .data
    #该字符串为格式字符串,printf用该参数确定后续的参数个数
    firststring:    .ascii "Hello! %s is a %s who loves the number %d\0"
    name:            .ascii "Zhang\0"
    personstring:    .ascii "person\0"
    numberloved:    .long 3

.section .text
    .globl _start
    _start:        #注意传递参数顺序与函数原型中列出的顺序相反
                   pushl numberloved   #%d
                   pushl $personstring
                   pushl $name
                   pushl $firststring
                   call printf
                   
                   pushl $0
                   call exit

编译、链接、运行

as printf-example.s -o printf-example.o

ld printf-example.o -o printf-example -lc -dynamic-linker /lib/ld-linux.so.2

./printf-example

说明:(1)注意到参数的入栈顺序要逆序入栈

(2)即使所传递的参数不足一个字,也按一个字存储

(3)多数库在/usr/lib或/lib下,如果查看库中定义了哪些函数,用命令:objdump -R 库的完整路径

2、创建动态库

将上篇的write-record.s和read-record.s创建成动态库,其指令如下:

as write-record.s -o write-record.o

as read-record.s -o read-record.o

链接:ld -shared write-record.o read-record.o -o librecord.so

使用新建的库:as write-records.s -o write-records.o

ld -L . -dynamic-linker /lib/ld-linux.so.2 -o write-records -lrecord write-records.o

说明:(1)-L 告诉链接器在当前目录下搜索库(通常只搜索/lib 和 /usr/lib等库)

    (2)选项 -lrecord告诉链接器在librecord.so文件中搜索相应函数。

(3)动态连接器默认情况下只在/lib、/usr/lib 和/etc/ld.so.conf中搜索库,如果运行此程序,需添加当前地址运行库:

LD_LIBRARY_PATHS=.

export LD_LIBRARY_PATH

此时,直接输入./write-records即可执行程序。





你可能感兴趣的:(5、Linux汇编——动态链接库)