c語言函數(shù)調(diào)用過程
c語言函數(shù)調(diào)用過程
c語言函數(shù)你知道多少?它的調(diào)用過程你了解嗎?下面學(xué)習(xí)啦小編為大家介紹一下c語言函數(shù),希望對你有幫助。
c語言函數(shù)編譯環(huán)境
OS: Axianux 1.0
Compiler: gcc 3..2.3
Linker: Solaris Link Editors 5.x
Debug Tool: gdb
Editor: vi
c語言函數(shù)最簡C代碼分析
為簡化問題,來分析一下最簡的c代碼生成的匯編代碼:
# vi test1.c
int main()
{
return 0;
}
編譯該程序,產(chǎn)生二進(jìn)制文件:
# gcc -o start start.c
# file start
start: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, dynamically linked (uses shared libs), not stripped
start是一個ELF格式32位小端(Little Endian)的可執(zhí)行文件,動態(tài)鏈接并且符號表沒有去除。這正是Unix/Linux平臺典型的可執(zhí)行文件格式。
用gdb反匯編可以觀察生成的匯編代碼:
[wqf@15h166 attack]$ gdb start
GNU gdb Asianux (6.0post-0.20040223.17.1AX)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-asianux-linux-gnu"...(no debugging symbols found)...Using host libthread_db library "/lib/tls/libthread_db.so.1".
(gdb) disassemble main ---> 反匯編main函數(shù)
Dump of assembler code for function main:
0x08048310: push %ebp --->ebp寄存器內(nèi)容壓棧,即保存main函數(shù)的上級調(diào)用函數(shù)的?;刂?/p>
0x08048311: mov %esp,%ebp ---> esp值賦給ebp,設(shè)置main函數(shù)的?;?/p>
0x08048313: sub
c語言函數(shù)調(diào)用過程
c語言函數(shù)調(diào)用過程
c語言函數(shù)你知道多少?它的調(diào)用過程你了解嗎?下面學(xué)習(xí)啦小編為大家介紹一下c語言函數(shù),希望對你有幫助。
c語言函數(shù)編譯環(huán)境
OS: Axianux 1.0
Compiler: gcc 3..2.3
Linker: Solaris Link Editors 5.x
Debug Tool: gdb
Editor: vi
c語言函數(shù)最簡C代碼分析
為簡化問題,來分析一下最簡的c代碼生成的匯編代碼:
# vi test1.c
int main()
{
return 0;
}
編譯該程序,產(chǎn)生二進(jìn)制文件:
# gcc -o start start.c
# file start
start: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, dynamically linked (uses shared libs), not stripped
start是一個ELF格式32位小端(Little Endian)的可執(zhí)行文件,動態(tài)鏈接并且符號表沒有去除。這正是Unix/Linux平臺典型的可執(zhí)行文件格式。
用gdb反匯編可以觀察生成的匯編代碼:
[wqf@15h166 attack]$ gdb start
GNU gdb Asianux (6.0post-0.20040223.17.1AX)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-asianux-linux-gnu"...(no debugging symbols found)...Using host libthread_db library "/lib/tls/libthread_db.so.1".
(gdb) disassemble main ---> 反匯編main函數(shù)
Dump of assembler code for function main:
0x08048310: push %ebp --->ebp寄存器內(nèi)容壓棧,即保存main函數(shù)的上級調(diào)用函數(shù)的?;刂?/p>
0x08048311: mov %esp,%ebp ---> esp值賦給ebp,設(shè)置main函數(shù)的棧基址
0x08048313: sub
0x08048316: and
c語言函數(shù)調(diào)用過程
c語言函數(shù)調(diào)用過程
c語言函數(shù)你知道多少?它的調(diào)用過程你了解嗎?下面學(xué)習(xí)啦小編為大家介紹一下c語言函數(shù),希望對你有幫助。
c語言函數(shù)編譯環(huán)境
OS: Axianux 1.0
Compiler: gcc 3..2.3
Linker: Solaris Link Editors 5.x
Debug Tool: gdb
Editor: vi
c語言函數(shù)最簡C代碼分析
為簡化問題,來分析一下最簡的c代碼生成的匯編代碼:
# vi test1.c
int main()
{
return 0;
}
編譯該程序,產(chǎn)生二進(jìn)制文件:
# gcc -o start start.c
# file start
start: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, dynamically linked (uses shared libs), not stripped
start是一個ELF格式32位小端(Little Endian)的可執(zhí)行文件,動態(tài)鏈接并且符號表沒有去除。這正是Unix/Linux平臺典型的可執(zhí)行文件格式。
用gdb反匯編可以觀察生成的匯編代碼:
[wqf@15h166 attack]$ gdb start
GNU gdb Asianux (6.0post-0.20040223.17.1AX)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-asianux-linux-gnu"...(no debugging symbols found)...Using host libthread_db library "/lib/tls/libthread_db.so.1".
(gdb) disassemble main ---> 反匯編main函數(shù)
Dump of assembler code for function main:
0x08048310: push %ebp --->ebp寄存器內(nèi)容壓棧,即保存main函數(shù)的上級調(diào)用函數(shù)的?;刂?/p>
0x08048311: mov %esp,%ebp ---> esp值賦給ebp,設(shè)置main函數(shù)的?;?/p>
0x08048313: sub
0x08048319: mov
c語言函數(shù)調(diào)用過程
c語言函數(shù)調(diào)用過程
c語言函數(shù)你知道多少?它的調(diào)用過程你了解嗎?下面學(xué)習(xí)啦小編為大家介紹一下c語言函數(shù),希望對你有幫助。
c語言函數(shù)編譯環(huán)境
OS: Axianux 1.0
Compiler: gcc 3..2.3
Linker: Solaris Link Editors 5.x
Debug Tool: gdb
Editor: vi
c語言函數(shù)最簡C代碼分析
為簡化問題,來分析一下最簡的c代碼生成的匯編代碼:
# vi test1.c
int main()
{
return 0;
}
編譯該程序,產(chǎn)生二進(jìn)制文件:
# gcc -o start start.c
# file start
start: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, dynamically linked (uses shared libs), not stripped
start是一個ELF格式32位小端(Little Endian)的可執(zhí)行文件,動態(tài)鏈接并且符號表沒有去除。這正是Unix/Linux平臺典型的可執(zhí)行文件格式。
用gdb反匯編可以觀察生成的匯編代碼:
[wqf@15h166 attack]$ gdb start
GNU gdb Asianux (6.0post-0.20040223.17.1AX)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-asianux-linux-gnu"...(no debugging symbols found)...Using host libthread_db library "/lib/tls/libthread_db.so.1".
(gdb) disassemble main ---> 反匯編main函數(shù)
Dump of assembler code for function main:
0x08048310: push %ebp --->ebp寄存器內(nèi)容壓棧,即保存main函數(shù)的上級調(diào)用函數(shù)的?;刂?/p>
0x08048311: mov %esp,%ebp ---> esp值賦給ebp,設(shè)置main函數(shù)的棧基址
0x08048313: sub
0x0804831e: sub %eax,%esp ---> 無意義
0x08048320: mov
c語言函數(shù)調(diào)用過程
c語言函數(shù)調(diào)用過程
c語言函數(shù)你知道多少?它的調(diào)用過程你了解嗎?下面學(xué)習(xí)啦小編為大家介紹一下c語言函數(shù),希望對你有幫助。
c語言函數(shù)編譯環(huán)境
OS: Axianux 1.0
Compiler: gcc 3..2.3
Linker: Solaris Link Editors 5.x
Debug Tool: gdb
Editor: vi
c語言函數(shù)最簡C代碼分析
為簡化問題,來分析一下最簡的c代碼生成的匯編代碼:
# vi test1.c
int main()
{
return 0;
}
編譯該程序,產(chǎn)生二進(jìn)制文件:
# gcc -o start start.c
# file start
start: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, dynamically linked (uses shared libs), not stripped
start是一個ELF格式32位小端(Little Endian)的可執(zhí)行文件,動態(tài)鏈接并且符號表沒有去除。這正是Unix/Linux平臺典型的可執(zhí)行文件格式。
用gdb反匯編可以觀察生成的匯編代碼:
[wqf@15h166 attack]$ gdb start
GNU gdb Asianux (6.0post-0.20040223.17.1AX)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-asianux-linux-gnu"...(no debugging symbols found)...Using host libthread_db library "/lib/tls/libthread_db.so.1".
(gdb) disassemble main ---> 反匯編main函數(shù)
Dump of assembler code for function main:
0x08048310: push %ebp --->ebp寄存器內(nèi)容壓棧,即保存main函數(shù)的上級調(diào)用函數(shù)的?;刂?/p>
0x08048311: mov %esp,%ebp ---> esp值賦給ebp,設(shè)置main函數(shù)的?;?/p>
0x08048313: sub
0x08048325: leave --->將ebp值賦給esp,pop先前棧內(nèi)的上級函數(shù)棧的基地址給ebp,恢復(fù)原?;?
0x08048326: ret ---> main函數(shù)返回,回到上級調(diào)用.
0x08048327: nop
End of assembler dump.
注:這里得到的匯編語言語法格式與Intel的手冊有很大不同,Unix/Linux采用AT&T匯編格式作為匯編語言的語法格式,如果想了解AT&T匯編可以參考文章 Linux 匯編語言開發(fā)指南.
問題一:誰調(diào)用了 main函數(shù)?
在C語言的層面來看,main函數(shù)是一個程序的起始入口點,而實際上,ELF可執(zhí)行文件的入口點并不是main而是_start。
gdb也可以反匯編_start:
(gdb)disass _start --->從_start的地址開始反匯編
Dump of assembler code for function _start:
0x08048264 <_start+0>: xor %ebp,%ebp
0x08048266 <_start+2>: pop %esi
0x08048267 <_start+3>: mov %esp,%ecx
0x08048269 <_start+5>: and
c語言函數(shù)調(diào)用過程
c語言函數(shù)調(diào)用過程
c語言函數(shù)你知道多少?它的調(diào)用過程你了解嗎?下面學(xué)習(xí)啦小編為大家介紹一下c語言函數(shù),希望對你有幫助。
c語言函數(shù)編譯環(huán)境
OS: Axianux 1.0
Compiler: gcc 3..2.3
Linker: Solaris Link Editors 5.x
Debug Tool: gdb
Editor: vi
c語言函數(shù)最簡C代碼分析
為簡化問題,來分析一下最簡的c代碼生成的匯編代碼:
# vi test1.c
int main()
{
return 0;
}
編譯該程序,產(chǎn)生二進(jìn)制文件:
# gcc -o start start.c
# file start
start: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, dynamically linked (uses shared libs), not stripped
start是一個ELF格式32位小端(Little Endian)的可執(zhí)行文件,動態(tài)鏈接并且符號表沒有去除。這正是Unix/Linux平臺典型的可執(zhí)行文件格式。
用gdb反匯編可以觀察生成的匯編代碼:
[wqf@15h166 attack]$ gdb start
GNU gdb Asianux (6.0post-0.20040223.17.1AX)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-asianux-linux-gnu"...(no debugging symbols found)...Using host libthread_db library "/lib/tls/libthread_db.so.1".
(gdb) disassemble main ---> 反匯編main函數(shù)
Dump of assembler code for function main:
0x08048310: push %ebp --->ebp寄存器內(nèi)容壓棧,即保存main函數(shù)的上級調(diào)用函數(shù)的?;刂?/p>
0x08048311: mov %esp,%ebp ---> esp值賦給ebp,設(shè)置main函數(shù)的?;?/p>
0x08048313: sub
0x0804826c <_start+8>: push %eax
0x0804826d <_start+9>: push %esp
0x0804826e <_start+10>: push %edx
0x0804826f <_start+11>: push
c語言函數(shù)調(diào)用過程
c語言函數(shù)調(diào)用過程
c語言函數(shù)你知道多少?它的調(diào)用過程你了解嗎?下面學(xué)習(xí)啦小編為大家介紹一下c語言函數(shù),希望對你有幫助。
c語言函數(shù)編譯環(huán)境
OS: Axianux 1.0
Compiler: gcc 3..2.3
Linker: Solaris Link Editors 5.x
Debug Tool: gdb
Editor: vi
c語言函數(shù)最簡C代碼分析
為簡化問題,來分析一下最簡的c代碼生成的匯編代碼:
# vi test1.c
int main()
{
return 0;
}
編譯該程序,產(chǎn)生二進(jìn)制文件:
# gcc -o start start.c
# file start
start: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, dynamically linked (uses shared libs), not stripped
start是一個ELF格式32位小端(Little Endian)的可執(zhí)行文件,動態(tài)鏈接并且符號表沒有去除。這正是Unix/Linux平臺典型的可執(zhí)行文件格式。
用gdb反匯編可以觀察生成的匯編代碼:
[wqf@15h166 attack]$ gdb start
GNU gdb Asianux (6.0post-0.20040223.17.1AX)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-asianux-linux-gnu"...(no debugging symbols found)...Using host libthread_db library "/lib/tls/libthread_db.so.1".
(gdb) disassemble main ---> 反匯編main函數(shù)
Dump of assembler code for function main:
0x08048310: push %ebp --->ebp寄存器內(nèi)容壓棧,即保存main函數(shù)的上級調(diào)用函數(shù)的棧基地址
0x08048311: mov %esp,%ebp ---> esp值賦給ebp,設(shè)置main函數(shù)的?;?/p>
0x08048313: sub
0x08048274 <_start+16>: push
c語言函數(shù)調(diào)用過程
c語言函數(shù)調(diào)用過程
c語言函數(shù)你知道多少?它的調(diào)用過程你了解嗎?下面學(xué)習(xí)啦小編為大家介紹一下c語言函數(shù),希望對你有幫助。
c語言函數(shù)編譯環(huán)境
OS: Axianux 1.0
Compiler: gcc 3..2.3
Linker: Solaris Link Editors 5.x
Debug Tool: gdb
Editor: vi
c語言函數(shù)最簡C代碼分析
為簡化問題,來分析一下最簡的c代碼生成的匯編代碼:
# vi test1.c
int main()
{
return 0;
}
編譯該程序,產(chǎn)生二進(jìn)制文件:
# gcc -o start start.c
# file start
start: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, dynamically linked (uses shared libs), not stripped
start是一個ELF格式32位小端(Little Endian)的可執(zhí)行文件,動態(tài)鏈接并且符號表沒有去除。這正是Unix/Linux平臺典型的可執(zhí)行文件格式。
用gdb反匯編可以觀察生成的匯編代碼:
[wqf@15h166 attack]$ gdb start
GNU gdb Asianux (6.0post-0.20040223.17.1AX)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-asianux-linux-gnu"...(no debugging symbols found)...Using host libthread_db library "/lib/tls/libthread_db.so.1".
(gdb) disassemble main ---> 反匯編main函數(shù)
Dump of assembler code for function main:
0x08048310: push %ebp --->ebp寄存器內(nèi)容壓棧,即保存main函數(shù)的上級調(diào)用函數(shù)的?;刂?/p>
0x08048311: mov %esp,%ebp ---> esp值賦給ebp,設(shè)置main函數(shù)的?;?/p>
0x08048313: sub
0x08048279 <_start+21>: push %ecx
0x0804827a <_start+22>: push %esi
0x0804827b <_start+23>: push
c語言函數(shù)調(diào)用過程
c語言函數(shù)調(diào)用過程
c語言函數(shù)你知道多少?它的調(diào)用過程你了解嗎?下面學(xué)習(xí)啦小編為大家介紹一下c語言函數(shù),希望對你有幫助。
c語言函數(shù)編譯環(huán)境
OS: Axianux 1.0
Compiler: gcc 3..2.3
Linker: Solaris Link Editors 5.x
Debug Tool: gdb
Editor: vi
c語言函數(shù)最簡C代碼分析
為簡化問題,來分析一下最簡的c代碼生成的匯編代碼:
# vi test1.c
int main()
{
return 0;
}
編譯該程序,產(chǎn)生二進(jìn)制文件:
# gcc -o start start.c
# file start
start: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, dynamically linked (uses shared libs), not stripped
start是一個ELF格式32位小端(Little Endian)的可執(zhí)行文件,動態(tài)鏈接并且符號表沒有去除。這正是Unix/Linux平臺典型的可執(zhí)行文件格式。
用gdb反匯編可以觀察生成的匯編代碼:
[wqf@15h166 attack]$ gdb start
GNU gdb Asianux (6.0post-0.20040223.17.1AX)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-asianux-linux-gnu"...(no debugging symbols found)...Using host libthread_db library "/lib/tls/libthread_db.so.1".
(gdb) disassemble main ---> 反匯編main函數(shù)
Dump of assembler code for function main:
0x08048310: push %ebp --->ebp寄存器內(nèi)容壓棧,即保存main函數(shù)的上級調(diào)用函數(shù)的?;刂?/p>
0x08048311: mov %esp,%ebp ---> esp值賦給ebp,設(shè)置main函數(shù)的?;?/p>
0x08048313: sub
0x08048280 <_start+28>: call 0x8048254 <__libc_start_main>
--->在這里調(diào)用了main函數(shù)
0x08048285 <_start+33>: hlt
0x08048286 <_start+34>: nop
0x08048287 <_start+35>: nop
End of assembler dump.
問題二:為什么用EAX寄存器保存函數(shù)返回值?
實際上IA32并沒有規(guī)定用哪個寄存器來保存返回值。但是,如果反匯編Solaris/Linux的二進(jìn)制文件,就會發(fā)現(xiàn),都用EAX保存函數(shù)返回值。
這不是偶然現(xiàn)象,是操作系統(tǒng)的ABI(Application Binary Interface)來決定的。
Solaris/Linux操作系統(tǒng)的ABI就是Sytem V ABI。
概念三:SFP (Stack Frame Pointer) 棧幀指針
正確理解SFP必須了解:
IA32 的棧的概念
CPU 中32位寄存器ESP/EBP的作用
PUSH/POP 指令是如何影響棧的
CALL/RET/LEAVE 等指令是如何影響棧的
如我們所知:
1) IA32的棧是用來存放臨時數(shù)據(jù),而且是LIFO,即后進(jìn)先出的。棧的增長方向是從高地址向低地址增長,按字節(jié)為單位編址。
2) EBP是?;返闹羔?,永遠(yuǎn)指向棧底(高地址),ESP是棧指針,永遠(yuǎn)指向棧頂(低地址)。
3) PUSH一個long型數(shù)據(jù)時,以字節(jié)為單位將數(shù)據(jù)壓入棧,從高到低按字節(jié)依次將數(shù)據(jù)存入ESP-1、ESP-2、ESP-3、ESP-4的地址單元。
4) POP一個long型數(shù)據(jù),過程與PUSH相反,依次將ESP-4、ESP-3、ESP-2、ESP-1從棧內(nèi)彈出,放入一個32位寄存器。
5) CALL指令用來調(diào)用一個函數(shù)或過程,此時,下一條指令地址會被壓入堆棧,以備返回時能恢復(fù)執(zhí)行下條指令。
6) RET指令用來從一個函數(shù)或過程返回,之前CALL保存的下條指令地址會從棧內(nèi)彈出到EIP寄存器中,程序轉(zhuǎn)到CALL之前下條指令處執(zhí)行。
7) ENTER是建立當(dāng)前函數(shù)的??蚣埽聪喈?dāng)于以下兩條指令:
pushl %ebp
movl %esp,%ebp
8) LEAVE是釋放當(dāng)前函數(shù)或者過程的??蚣埽聪喈?dāng)于以下兩條指令:
movl ebp, esp
popl ebp
原來編譯器會自動在函數(shù)入口和出口處插入創(chuàng)建和釋放??蚣艿恼Z句。
函數(shù)被調(diào)用時:
1) EIP/EBP成為新函數(shù)棧的邊界
函數(shù)被調(diào)用時,返回時的EIP首先被壓入堆棧;創(chuàng)建棧框架時,上級函數(shù)棧的EBP被壓入堆棧,與EIP一道行成新函數(shù)棧框架的邊界。
2) EBP成為棧幀指針STP,用來指示新函數(shù)棧的邊界
棧幀建立后,EBP指向的棧的內(nèi)容就是上一級函數(shù)棧的EBP,可以想象,通過EBP就可以把層層調(diào)用函數(shù)的棧都回朔遍歷一遍,調(diào)試器就是利用這個特性實現(xiàn)backtrace功能的。
3) ESP總是作為棧指針指向棧頂,用來分配??臻g
棧分配空間給函數(shù)局部變量時的語句通常就是給ESP減去一個常數(shù)值,例如,分配一個整型數(shù)據(jù)就是 ESP-4。
4) 函數(shù)的參數(shù)傳遞和局部變量訪問可以通過STP即EBP來實現(xiàn)
由于??蚣苤羔樣肋h(yuǎn)指向當(dāng)前函數(shù)的?;刂?,參數(shù)和局部變量訪問通常為如下形式:
+8+xx(%ebp) :函數(shù)入口參數(shù)的的訪問
-xx(%ebp) :函數(shù)局部變量訪問
假如函數(shù)A調(diào)用函數(shù)B,函數(shù)B調(diào)用函數(shù)C ,則函數(shù)棧幀及調(diào)用關(guān)系如下圖所示:
+----------------------+----> 高地址 | EIP (上級函數(shù)返回地址) | +----------------------+ +--> | EBP (上級函數(shù)的EBP) | --+ <------ 當(dāng)前函數(shù)A的EBP (即STP框架指針) | +----------------------+ +-->偏移量A | | Local Variables | | | | .......... | --+ <------ ESP指向函數(shù)A新分配的局部變量,局部變量可以通過A的ebp-偏移量A訪問 | f +----------------------+ | r | Arg n(函數(shù)B的第n個參數(shù)) | | a +----------------------+ | m | Arg .(函數(shù)B的第.個參數(shù)) | | e +----------------------+ | | Arg 1(函數(shù)B的第1個參數(shù)) | | o +----------------------+ | f | Arg 0(函數(shù)B的第0個參數(shù)) | --+ <------ B函數(shù)的參數(shù)可以由B的ebp+偏移量B訪問 | +----------------------+ +--> 偏移量B | A | EIP (A函數(shù)的返回地址) | | | +----------------------+ --+ +--- | EBP (A函數(shù)的EBP) |<--+ <------ 當(dāng)前函數(shù)B的EBP (即STP框架指針) +----------------------+ | | Local Variables | | | .......... | | <------ ESP指向函數(shù)B新分配的局部變量 +----------------------+ | | Arg n(函數(shù)C的第n個參數(shù)) | | +----------------------+ | | Arg .(函數(shù)C的第.個參數(shù)) | | +----------------------+ +--> frame of B | Arg 1(函數(shù)C的第1個參數(shù)) | | +----------------------+ | | Arg 0(函數(shù)C的第0個參數(shù)) | | +----------------------+ | | EIP (B函數(shù)的返回地址) | | +----------------------+ | +--> | EBP (B函數(shù)的EBP) |---+ <------ 當(dāng)前函數(shù)C的EBP (即STP框架指針) | +----------------------+ | | Local Variables | | | .......... | <------ ESP指向函數(shù)C新分配的局部變量 | +----------------------+----> 低地址frame of C
概念四:Stack aligned 棧對齊
那么,以下語句到底是和作用呢?
subl ,%esp
andl
c語言函數(shù)調(diào)用過程
c語言函數(shù)調(diào)用過程
c語言函數(shù)你知道多少?它的調(diào)用過程你了解嗎?下面學(xué)習(xí)啦小編為大家介紹一下c語言函數(shù),希望對你有幫助。
c語言函數(shù)編譯環(huán)境
OS: Axianux 1.0
Compiler: gcc 3..2.3
Linker: Solaris Link Editors 5.x
Debug Tool: gdb
Editor: vi
c語言函數(shù)最簡C代碼分析
為簡化問題,來分析一下最簡的c代碼生成的匯編代碼:
# vi test1.c
int main()
{
return 0;
}
編譯該程序,產(chǎn)生二進(jìn)制文件:
# gcc -o start start.c
# file start
start: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, dynamically linked (uses shared libs), not stripped
start是一個ELF格式32位小端(Little Endian)的可執(zhí)行文件,動態(tài)鏈接并且符號表沒有去除。這正是Unix/Linux平臺典型的可執(zhí)行文件格式。
用gdb反匯編可以觀察生成的匯編代碼:
[wqf@15h166 attack]$ gdb start
GNU gdb Asianux (6.0post-0.20040223.17.1AX)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-asianux-linux-gnu"...(no debugging symbols found)...Using host libthread_db library "/lib/tls/libthread_db.so.1".
(gdb) disassemble main ---> 反匯編main函數(shù)
Dump of assembler code for function main:
0x08048310: push %ebp --->ebp寄存器內(nèi)容壓棧,即保存main函數(shù)的上級調(diào)用函數(shù)的?;刂?/p>
0x08048311: mov %esp,%ebp ---> esp值賦給ebp,設(shè)置main函數(shù)的棧基址
0x08048313: sub
表面來看,這條語句最直接的后果是使ESP的地址后4位為0,即16字節(jié)對齊,那么為什么這么做呢?
原來,IA32 系列CPU的一些指令分別在4、8、16字節(jié)對齊時會有更加的運行速度,因此gcc編譯器為提高生成代碼在IA32上的運行速度,默認(rèn)對產(chǎn)生的代碼進(jìn)行16字節(jié)對齊.
andl
c語言函數(shù)調(diào)用過程
c語言函數(shù)調(diào)用過程
c語言函數(shù)你知道多少?它的調(diào)用過程你了解嗎?下面學(xué)習(xí)啦小編為大家介紹一下c語言函數(shù),希望對你有幫助。
c語言函數(shù)編譯環(huán)境
OS: Axianux 1.0
Compiler: gcc 3..2.3
Linker: Solaris Link Editors 5.x
Debug Tool: gdb
Editor: vi
c語言函數(shù)最簡C代碼分析
為簡化問題,來分析一下最簡的c代碼生成的匯編代碼:
# vi test1.c
int main()
{
return 0;
}
編譯該程序,產(chǎn)生二進(jìn)制文件:
# gcc -o start start.c
# file start
start: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, dynamically linked (uses shared libs), not stripped
start是一個ELF格式32位小端(Little Endian)的可執(zhí)行文件,動態(tài)鏈接并且符號表沒有去除。這正是Unix/Linux平臺典型的可執(zhí)行文件格式。
用gdb反匯編可以觀察生成的匯編代碼:
[wqf@15h166 attack]$ gdb start
GNU gdb Asianux (6.0post-0.20040223.17.1AX)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-asianux-linux-gnu"...(no debugging symbols found)...Using host libthread_db library "/lib/tls/libthread_db.so.1".
(gdb) disassemble main ---> 反匯編main函數(shù)
Dump of assembler code for function main:
0x08048310: push %ebp --->ebp寄存器內(nèi)容壓棧,即保存main函數(shù)的上級調(diào)用函數(shù)的?;刂?/p>
0x08048311: mov %esp,%ebp ---> esp值賦給ebp,設(shè)置main函數(shù)的?;?/p>
0x08048313: sub
如果查一下gcc的手冊,就會發(fā)現(xiàn)關(guān)于棧對齊的參數(shù)設(shè)置:
-mpreferred-stack-boundary=n ---> 希望棧按照2的n次的字節(jié)邊界對齊, n的取值范圍是2-12.
默認(rèn)情況下,n是等于4的,也就是說,默認(rèn)情況下,gcc是16字節(jié)對齊,以適應(yīng)IA32大多數(shù)指令的要求。
讓我們利用-mpreferred-stack-boundary=2來去除棧對齊指令:
(gdb) disass main
Dump of assembler code for function main:
0x08048310: push %ebp
0x08048311: mov %esp,%ebp
0x08048313: mov
c語言函數(shù)調(diào)用過程
c語言函數(shù)調(diào)用過程
c語言函數(shù)你知道多少?它的調(diào)用過程你了解嗎?下面學(xué)習(xí)啦小編為大家介紹一下c語言函數(shù),希望對你有幫助。
c語言函數(shù)編譯環(huán)境
OS: Axianux 1.0
Compiler: gcc 3..2.3
Linker: Solaris Link Editors 5.x
Debug Tool: gdb
Editor: vi
c語言函數(shù)最簡C代碼分析
為簡化問題,來分析一下最簡的c代碼生成的匯編代碼:
# vi test1.c
int main()
{
return 0;
}
編譯該程序,產(chǎn)生二進(jìn)制文件:
# gcc -o start start.c
# file start
start: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, dynamically linked (uses shared libs), not stripped
start是一個ELF格式32位小端(Little Endian)的可執(zhí)行文件,動態(tài)鏈接并且符號表沒有去除。這正是Unix/Linux平臺典型的可執(zhí)行文件格式。
用gdb反匯編可以觀察生成的匯編代碼:
[wqf@15h166 attack]$ gdb start
GNU gdb Asianux (6.0post-0.20040223.17.1AX)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-asianux-linux-gnu"...(no debugging symbols found)...Using host libthread_db library "/lib/tls/libthread_db.so.1".
(gdb) disassemble main ---> 反匯編main函數(shù)
Dump of assembler code for function main:
0x08048310: push %ebp --->ebp寄存器內(nèi)容壓棧,即保存main函數(shù)的上級調(diào)用函數(shù)的?;刂?/p>
0x08048311: mov %esp,%ebp ---> esp值賦給ebp,設(shè)置main函數(shù)的棧基址
0x08048313: sub
0x08048318: leave
0x08048319: ret
0x0804831a: nop
0x0804831b: nop
End of assembler dump.
可以看到,棧對齊指令沒有了,因為,IA32的棧本身就是4字節(jié)對齊的,不需要用額外指令進(jìn)行對齊。
問題五:??蚣苤羔楽TP是不是必須的呢?
[wqf@15h166attack]$ gcc -mpreferred-stack-boundary=2 -fomit-frame-pointer start.c -o start
[wqf@15h166attack]$ gdb start
(gdb) disass main
Dump of assembler code for function main:
0x08048310: mov
c語言函數(shù)調(diào)用過程
c語言函數(shù)調(diào)用過程
c語言函數(shù)你知道多少?它的調(diào)用過程你了解嗎?下面學(xué)習(xí)啦小編為大家介紹一下c語言函數(shù),希望對你有幫助。
c語言函數(shù)編譯環(huán)境
OS: Axianux 1.0
Compiler: gcc 3..2.3
Linker: Solaris Link Editors 5.x
Debug Tool: gdb
Editor: vi
c語言函數(shù)最簡C代碼分析
為簡化問題,來分析一下最簡的c代碼生成的匯編代碼:
# vi test1.c
int main()
{
return 0;
}
編譯該程序,產(chǎn)生二進(jìn)制文件:
# gcc -o start start.c
# file start
start: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, dynamically linked (uses shared libs), not stripped
start是一個ELF格式32位小端(Little Endian)的可執(zhí)行文件,動態(tài)鏈接并且符號表沒有去除。這正是Unix/Linux平臺典型的可執(zhí)行文件格式。
用gdb反匯編可以觀察生成的匯編代碼:
[wqf@15h166 attack]$ gdb start
GNU gdb Asianux (6.0post-0.20040223.17.1AX)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-asianux-linux-gnu"...(no debugging symbols found)...Using host libthread_db library "/lib/tls/libthread_db.so.1".
(gdb) disassemble main ---> 反匯編main函數(shù)
Dump of assembler code for function main:
0x08048310: push %ebp --->ebp寄存器內(nèi)容壓棧,即保存main函數(shù)的上級調(diào)用函數(shù)的?;刂?/p>
0x08048311: mov %esp,%ebp ---> esp值賦給ebp,設(shè)置main函數(shù)的?;?/p>
0x08048313: sub
0x08048315: ret
0x08048316: nop
0x08048317: nop
End of assembler dump.
由此可知,-fomit-frame-pointer 可以去除STP。
去除STP后有什么缺點呢?
1)增加調(diào)式難度
由于STP在調(diào)試器backtrace的指令中被使用到,因此沒有STP該調(diào)試指令就無法使用。
2)降低匯編代碼可讀性
函數(shù)參數(shù)和局部變量的訪問,在沒有ebp的情況下,都只能通過+xx(esp)的方式訪問,而很難區(qū)分兩種方式,降低了程序的可讀性。
去除STP有什么優(yōu)點呢?
1)節(jié)省棧空間。
2)減少建立和撤銷??蚣艿闹噶詈?,簡化了代碼。
3)使ebp空閑出來,使之作為通用寄存器使用,增加通用寄存器的數(shù)量
4)以上3點使得程序運行速度更快。
概念六:Calling Convention 調(diào)用約定和ABI (Application Binary Interface) 應(yīng)用程序二進(jìn)制接口。
函數(shù)如何找到它的參數(shù)?
函數(shù)如何返回結(jié)果?
函數(shù)在哪里存放局部變量?
哪一個硬件寄存器是起始空間?
哪一個硬件寄存器必須預(yù)先保留?
Calling Convention 調(diào)用約定對以上問題作出了規(guī)定。Calling Convention也是ABI的一部分。因此,遵守相同ABI規(guī)范的操作系統(tǒng),使其相互間實現(xiàn)二進(jìn)制代碼的互操作成為了可能。
例如:由于Solaris、Linux都遵守System V的ABI,Solaris 10就提供了直接運行Linux二進(jìn)制程序的功能。
c語言函數(shù)小結(jié)
本文通過最簡的C程序,引出以下概念:
STP ??蚣苤羔?/p>
Stack aligned 棧對齊
Calling Convention 調(diào)用約定 和 ABI (Application Binary Interface) 應(yīng)用程序二進(jìn)制接口
看了“c語言函數(shù)調(diào)用過程”的人還看了: