日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

汇编语言使用C库函数和Linux动态链接

發(fā)布時間:2023/11/27 生活经验 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 汇编语言使用C库函数和Linux动态链接 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

使用printf


代碼

#cpuid2.s -- Using C labrary calls  
.section .data  
output:          .asciz "The processor Vender is '%s'\n"
.section .bss          .lcomm buffer, 12  
.section .text  
.globl _start  
_start:          movl $0, %eax          cpuid          movl $buffer, %edi          movl %ebx, (%edi)   //含義同cpuid.s,向%edi所指向的buffer內(nèi)存          movl %edx, 4(%edi)  //位置寫入3個寄存器的內(nèi)容,這3個寄存器存儲了          movl %ecx, 8(%edi)  //CPU廠商信息的字符串(12字節(jié))          pushl $buffer       //將buffer和output入棧,為printf提供參數(shù)          pushl $output          call printf         //調(diào)用C的printf函數(shù)          addl $8, %esp       //將堆棧指針回滾8個字節(jié),達(dá)到清除printf參數(shù)的目的          pushl $0          call exit


?

.asciz是在定義字符串的時侯在字符串結(jié)尾加上空字符(即C語言的\0),這樣做的目的是為了讓printf能讀懂字符串。

.lcomm是在本地內(nèi)存區(qū)域中聲明固定長度的未初始化數(shù)據(jù),這里初始化了12個字節(jié)的空間。

程序里buffer和output內(nèi)存位置的內(nèi)容是要向printf傳遞的參數(shù)值:

一個是"The processor Vender is '%s'\n"字符串;

另外一個是由cpuid返回結(jié)果(在ebx,edx,ecx三個寄存器中)填充的buffer。


需要通過堆棧來傳遞參數(shù),所以在程序中使用

pushl $buffer

pushl $output

將參數(shù)入棧,printf獲取參數(shù)是自右向左,即先buffer后output,所以要把buffer后入棧。

參數(shù)入棧之后,用call指令調(diào)用printf。

exit的情況同上,使用了一個參數(shù)--常數(shù)0。


匯編

#as -o cpuid2.o cpuid2.s

采用了動態(tài)連接的方式,所以C函數(shù)沒有包含在可執(zhí)行程序中,需要由另外的程序在運(yùn)行時加載,ld不知道這個程序在哪里,所以我們還得手動指定

動態(tài)鏈接

#ld -dynamic-linker /lib/ld-linux.so.2 -lc -o cpuid2 cpuid2.o

#./cpuid2

輸出

The processor Vendor ID is 'GenuineIntel'

GDB調(diào)試

# gdb cpuid2  
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-56.el6)
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /usr/zhms/AS/chap04/cpuid2...done.
(gdb) break _start
Breakpoint 1 at 0x80481b8: file cpuid2.s, line 10.
(gdb) r
Starting program: /usr/zhms/AS/chap04/cpuid2 Breakpoint 1, _start () at cpuid2.s:10
10          movl $0, %eax
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.80.el6_3.6.i686
(gdb) i r
eax            0x0      0
ecx            0x0      0
edx            0x758470 7701616
ebx            0x767fc4 7765956
esp            0xbffff6c0       0xbffff6c0
ebp            0x0      0x0
esi            0xbffff6cc       -1073744180
edi            0x80481b8        134513080
eip            0x80481b8        0x80481b8 <_start>
eflags         0x286    [ PF SF IF ]
cs             0x73     115
ss             0x7b     123
ds             0x7b     123
es             0x7b     123
fs             0x0      0
gs             0x33     51
(gdb) s
11          cpuid
(gdb) i r
eax            0x0      0
ecx            0x0      0
edx            0x758470 7701616
ebx            0x767fc4 7765956
esp            0xbffff6c0       0xbffff6c0
ebp            0x0      0x0
esi            0xbffff6cc       -1073744180
edi            0x80481b8        134513080
eip            0x80481bd        0x80481bd <_start+5>
eflags         0x286    [ PF SF IF ]
cs             0x73     115
ss             0x7b     123
ds             0x7b     123
es             0x7b     123
fs             0x0      0
gs             0x33     51
(gdb) s
13          movl %ebx, (%edi)
(gdb) i r
eax            0x5      5
ecx            0x6c65746e       1818588270
edx            0x49656e69       1231384169
ebx            0x756e6547       1970169159
esp            0xbffff6c0       0xbffff6c0
ebp            0x0      0x0
esi            0xbffff6cc       -1073744180
edi            0x80492c0        134517440
eip            0x80481c4        0x80481c4 <_start+12>
eflags         0x286    [ PF SF IF ]
cs             0x73     115
ss             0x7b     123
ds             0x7b     123
es             0x7b     123
fs             0x0      0
gs             0x33     51
(gdb) s
14          movl %edx, 4(%edi)
(gdb) i r
eax            0x5      5
ecx            0x6c65746e       1818588270
edx            0x49656e69       1231384169
ebx            0x756e6547       1970169159
esp            0xbffff6c0       0xbffff6c0
ebp            0x0      0x0
esi            0xbffff6cc       -1073744180
edi            0x80492c0        134517440
eip            0x80481c6        0x80481c6 <_start+14>
eflags         0x286    [ PF SF IF ]
cs             0x73     115
ss             0x7b     123
ds             0x7b     123
es             0x7b     123
fs             0x0      0
gs             0x33     51
(gdb) s
15          movl %ecx, 8(%edi)
(gdb) i r
eax            0x5      5
ecx            0x6c65746e       1818588270
edx            0x49656e69       1231384169
ebx            0x756e6547       1970169159
esp            0xbffff6c0       0xbffff6c0
ebp            0x0      0x0
esi            0xbffff6cc       -1073744180
edi            0x80492c0        134517440
eip            0x80481c9        0x80481c9 <_start+17>
eflags         0x286    [ PF SF IF ]
cs             0x73     115
ss             0x7b     123
ds             0x7b     123
es             0x7b     123
fs             0x0      0
gs             0x33     51
(gdb) s
16          pushl $buffer
(gdb) i r
eax            0x5      5
ecx            0x6c65746e       1818588270
edx            0x49656e69       1231384169
ebx            0x756e6547       1970169159
esp            0xbffff6c0       0xbffff6c0
ebp            0x0      0x0
esi            0xbffff6cc       -1073744180
edi            0x80492c0        134517440
eip            0x80481cc        0x80481cc <_start+20>
eflags         0x286    [ PF SF IF ]
cs             0x73     115
ss             0x7b     123
ds             0x7b     123
es             0x7b     123
fs             0x0      0
gs             0x33     51
(gdb) s
17          pushl $output
(gdb) i r
eax            0x5      5
ecx            0x6c65746e       1818588270
edx            0x49656e69       1231384169
ebx            0x756e6547       1970169159
esp            0xbffff6bc       0xbffff6bc
ebp            0x0      0x0
esi            0xbffff6cc       -1073744180
edi            0x80492c0        134517440
eip            0x80481d1        0x80481d1 <_start+25>
eflags         0x286    [ PF SF IF ]
cs             0x73     115
ss             0x7b     123
ds             0x7b     123
es             0x7b     123
fs             0x0      0
gs             0x33     51
(gdb) s
18          call printf
(gdb) i r
eax            0x5      5
ecx            0x6c65746e       1818588270
edx            0x49656e69       1231384169
ebx            0x756e6547       1970169159
esp            0xbffff6b8       0xbffff6b8
ebp            0x0      0x0
esi            0xbffff6cc       -1073744180
edi            0x80492c0        134517440
eip            0x80481d6        0x80481d6 <_start+30>
eflags         0x286    [ PF SF IF ]
cs             0x73     115
ss             0x7b     123
ds             0x7b     123
es             0x7b     123
fs             0x0      0
gs             0x33     51
(gdb) s
0x007b63e0 in printf () from /lib/libc.so.6
(gdb) i r
eax            0x5      5
ecx            0x6c65746e       1818588270
edx            0x49656e69       1231384169
ebx            0x756e6547       1970169159
esp            0xbffff6b4       0xbffff6b4
ebp            0x0      0x0
esi            0xbffff6cc       -1073744180
edi            0x80492c0        134517440
eip            0x7b63e0 0x7b63e0 <printf>
eflags         0x246    [ PF ZF IF ]
cs             0x73     115
ss             0x7b     123
ds             0x7b     123
es             0x7b     123
fs             0x0      0
gs             0x33     51
(gdb) s
Single stepping until exit from function printf,
which has no line number information.
The processor Vendor ID is 'GenuineIntel'
_start () at cpuid2.s:19
19          addl $8, %esp
(gdb) i r
eax            0x2a     42
ecx            0xbffff6a0       -1073744224
edx            0x8fe364 9429860
ebx            0x756e6547       1970169159
esp            0xbffff6b8       0xbffff6b8
ebp            0x0      0x0
esi            0xbffff6cc       -1073744180
edi            0x80492c0        134517440
eip            0x80481db        0x80481db <_start+35>
eflags         0x286    [ PF SF IF ]
cs             0x73     115
ss             0x7b     123
ds             0x7b     123
es             0x7b     123
fs             0x0      0
gs             0x33     51
(gdb) s
20          pushl $0
(gdb) i r
eax            0x2a     42
ecx            0xbffff6a0       -1073744224
edx            0x8fe364 9429860
ebx            0x756e6547       1970169159
esp            0xbffff6c0       0xbffff6c0
ebp            0x0      0x0
esi            0xbffff6cc       -1073744180
edi            0x80492c0        134517440
eip            0x80481de        0x80481de <_start+38>
eflags         0x296    [ PF AF SF IF ]
cs             0x73     115
ss             0x7b     123
ds             0x7b     123
es             0x7b     123
fs             0x0      0
gs             0x33     51
(gdb) s
21          call exit
(gdb) i r
eax            0x2a     42
ecx            0xbffff6a0       -1073744224
edx            0x8fe364 9429860
ebx            0x756e6547       1970169159
esp            0xbffff6bc       0xbffff6bc
ebp            0x0      0x0
esi            0xbffff6cc       -1073744180
edi            0x80492c0        134517440
eip            0x80481e0        0x80481e0 <_start+40>
eflags         0x296    [ PF AF SF IF ]
cs             0x73     115
ss             0x7b     123
ds             0x7b     123
es             0x7b     123
fs             0x0      0
gs             0x33     51
(gdb) s
0x00799060 in exit () from /lib/libc.so.6
(gdb) i r
eax            0x2a     42
ecx            0xbffff6a0       -1073744224
edx            0x8fe364 9429860
ebx            0x756e6547       1970169159
esp            0xbffff6b8       0xbffff6b8
ebp            0x0      0x0
esi            0xbffff6cc       -1073744180
edi            0x80492c0        134517440
eip            0x799060 0x799060 <exit>
eflags         0x246    [ PF ZF IF ]
cs             0x73     115
ss             0x7b     123
ds             0x7b     123
es             0x7b     123
fs             0x0      0
gs             0x33     51
(gdb) s
Single stepping until exit from function exit,
which has no line number information.Program exited normally.
(gdb) i r
The program has no registers now.
(gdb) 


?

ld-linux.so查找共享庫的順序

這里引出一個問題,怎么知道ld-linux.so.2是什么以及定位

Glibc安裝的庫中有一個為ld-linux.so.X,其中X為一個數(shù)字,在不同的平臺上名字也會不同。可以用ldd查看:

#ldd /bin/cat

最后一個沒有=>的就是。其中第一個不是實(shí)際的庫文件,你是找不到的,它是一個虛擬庫文件用于和kernel交互。
ld-linux.so是專門負(fù)責(zé)尋找?guī)煳募膸臁R詂at為例,cat首先告訴ld-linux.so它需要libc.so.6這個庫文件,ld-linux.so將按一定順序找到libc.so.6庫再給cat調(diào)用。
那ld-linux.so又是怎么找到的呢?其實(shí)不用找,ld-linux.so的位置是寫死在程序中的,gcc在編譯程序時就寫死在里面了。Gcc寫到程序中l(wèi)d-linux.so的位置是可以改變的,通過修改gcc的spec文件。

運(yùn)行時,ld-linux.so查找共享庫的順序
(1)ld-linux.so.6在可執(zhí)行的目標(biāo)文件中被指定,可用readelf命令查看
(2)ld-linux.so.6缺省在/usr/lib和lib中搜索;當(dāng)glibc安裝到/usr/local下時,它查找/usr/local/lib
(3)LD_LIBRARY_PATH環(huán)境變量中所設(shè)定的路徑
(4)/etc/ld.so.conf(或/usr/local/etc/ld.so.conf)中所指定的路徑,由ldconfig生成二進(jìn)制的ld.so.cache中

編譯時,ld-linux.so查找共享庫的順序
(1)ld-linux.so.6由gcc的spec文件中所設(shè)定
(2)gcc --print-search-dirs所打印出的路徑,主要是libgcc_s.so等庫。可以通過GCC_EXEC_PREFIX來設(shè)定
(3)LIBRARY_PATH環(huán)境變量中所設(shè)定的路徑,或編譯的命令行中指定的-L/usr/local/lib
(4)binutils中的ld所設(shè)定的缺省搜索路徑順序,編譯binutils時指定。(可以通過“l(fā)d --verbose | grep SEARCH”來查看)
(5)二進(jìn)制程序的搜索路徑順序?yàn)镻ATH環(huán)境變量中所設(shè)定。一般/usr/local/bin高于/usr/bin
(6)編譯時的頭文件的搜索路徑順序,與library的查找順序類似。一般/usr/local/include高于/usr/include


用 Linux 進(jìn)行動態(tài)鏈接

ELF映像

Linux 中的動態(tài)鏈接的共享庫的過程。當(dāng)用戶啟動一個應(yīng)用程序時,它們正在調(diào)用一個可執(zhí)行和鏈接格式(Executable and Linking Format,ELF)映像。內(nèi)核首先將 ELF 映像加載到用戶空間虛擬內(nèi)存中。然后內(nèi)核會注意到一個稱為 .interp 的 ELF 部分,它指明了將要被使用的動態(tài)鏈接器(例如:/lib/ld-linux.so)。


一個ELF頭在文件的開始,保存了路線圖(road map),描述了該文件的組織情況。sections保存著object 文件的信息,從連接角度看:包括指令,數(shù)據(jù),符號表,重定位信息等等。

?

使用 readelf 來顯示程序標(biāo)題

#readelf -l cpuid2

注意,ld-linux.so 本身就是一個 ELF 共享庫,但它是靜態(tài)編譯的并且不具備共享庫依賴項(xiàng)。當(dāng)需要動態(tài)鏈接時,內(nèi)核會引導(dǎo)動態(tài)鏈接(ELF 解釋器),該鏈接首先會初始化自身,然后加載指定的共享對象(已加載則不必)。接著它會執(zhí)行必要的再定位,包括目標(biāo)共享對象所使用的共享對象。


#readelf -l cpuid2.o

There are no program headers in this file.


ldd命令

Linux 提供了很多種查看和解析 ELF 對象(包括共享庫)的工具。其中最有用的一個當(dāng)屬 ldd命令,可以使用它來發(fā)現(xiàn)共享庫依賴項(xiàng)

#ldd cpuid2

ldd所告訴您的是:該 ELF 映像依賴于 linux-gate.so(一個特殊的共享對象,它處理系統(tǒng)調(diào)用,它在文件系統(tǒng)中無關(guān)聯(lián)文件),GNU C庫(libc.so)以及 Linux 動態(tài)加載器(因?yàn)樗锩嬗泄蚕韼煲蕾図?xiàng))。


#ldd cpuid2.o

ldd: 警告: 你沒有執(zhí)行權(quán)限 `./cpuid2.o'
不是動態(tài)可執(zhí)行文件


readelf識別對象內(nèi)可再定位的C庫

readelf 命令是一個有很多特性的實(shí)用程序,它讓您能夠解析和讀取 ELF 對象。readelf 有一個有趣的用途,就是用來識別對象內(nèi)可再定位的項(xiàng)。對于我們這個簡單的程序來說,可以看到需要再定位的符號

#readelf -r cpuid2

從這個列表中,您可以看到各種各樣的需要再定位(到 libc.so)的 C庫調(diào)用。


#readelf -r cpuid2.o



readelf查看共享庫的依賴庫(NEEDED)和搜索名(SONAME)

#readelf -d cpuid2


#readelf -d cpuid2.o

無輸出


readelf查看ELF頭信息

#readelf -h cpuid2


#readelf -h cpuid2.o


附錄

#man readelf

?

objdump

objdump是用查看目標(biāo)文件或者可執(zhí)行的目標(biāo)文件的構(gòu)成的GCC工具


反匯編

#objdump -d cpuid2

對于其中的反匯編代碼

左邊是機(jī)器指令的字節(jié),右邊是反匯編結(jié)果。顯然,所有的符號都被替換成地址了, 注意沒有加$的數(shù)表示內(nèi)存地址,而不表示立即數(shù)。


objdump -x obj 以某種分類信息的形式把目標(biāo)文件的數(shù)據(jù)組織(被分為幾大塊)輸出 <可查到該文件的所有動態(tài)庫>
objdump -t obj 輸出目標(biāo)文件的符號表()
objdump -h obj 輸出目標(biāo)文件的所有段概括()
objdump -j .text/.data -S obj 輸出指定段的信息,大概就是反匯編源代碼把
objdump -S obj C語言與匯編語言同時顯示


更多參考

#man objdump

?

?

參考:Linux 動態(tài)庫剖析

http://www.ibm.com/developerworks/cn/linux/l-dynamic-libraries/

總結(jié)

以上是生活随笔為你收集整理的汇编语言使用C库函数和Linux动态链接的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。