五、Linux彙編——動態連接庫

一、使用動態連接庫

 (1)不調用庫函數

 下面的程序不使用動態庫,直接將hello world 輸出到屏幕上並退出。源代碼存放在文件helloworld-nolib.s中。linux

.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.ospa

ld hellowordl-nolib.o -o helloworld-nolibcode

(2)調用庫函數

下面程序將調用C庫中的printf函數和exit函數。功能仍是打印hello world,並退出程序。源代碼保存在helloworld-lib.s文件中。ci

.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 -lcstring

說明:(1)ld-linux.so.2文件是動態庫載入有關的文件,其主要做用是指導目標文件如何載入動態庫。其爲glibc的庫文件。it

(2)-lc表示鏈接到c庫,該庫在系統上的文件名爲libc.so,動態庫的通常格式爲:lib + 庫名 + .soio

(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 庫的完整路徑

二、建立動態庫

將上篇的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便可執行程序。

相關文章
相關標籤/搜索