c語(yǔ)言函數(shù)調(diào)用過程
c語(yǔ)言函數(shù)調(diào)用過程
c語(yǔ)言函數(shù)你知道多少?它的調(diào)用過程你了解嗎?下面學(xué)習(xí)啦小編為大家介紹一下c語(yǔ)言函數(shù),希望對(duì)你有幫助。
c語(yǔ)言函數(shù)編譯環(huán)境
OS: Axianux 1.0
Compiler: gcc 3..2.3
Linker: Solaris Link Editors 5.x
Debug Tool: gdb
Editor: vi
c語(yǔ)言函數(shù)最簡(jiǎn)C代碼分析
為簡(jiǎn)化問題,來(lái)分析一下最簡(jiǎn)的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是一個(gè)ELF格式32位小端(Little Endian)的可執(zhí)行文件,動(dòng)態(tài)鏈接并且符號(hào)表沒有去除。這正是Unix/Linux平臺(tái)典型的可執(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ù)的上級(jí)調(diào)用函數(shù)的?;刂?/p>
0x08048311: mov %esp,%ebp ---> esp值賦給ebp,設(shè)置main函數(shù)的?;?/p>
0x08048313: sub
c語(yǔ)言函數(shù)調(diào)用過程
c語(yǔ)言函數(shù)調(diào)用過程
c語(yǔ)言函數(shù)你知道多少?它的調(diào)用過程你了解嗎?下面學(xué)習(xí)啦小編為大家介紹一下c語(yǔ)言函數(shù),希望對(duì)你有幫助。
c語(yǔ)言函數(shù)編譯環(huán)境
OS: Axianux 1.0
Compiler: gcc 3..2.3
Linker: Solaris Link Editors 5.x
Debug Tool: gdb
Editor: vi
c語(yǔ)言函數(shù)最簡(jiǎn)C代碼分析
為簡(jiǎn)化問題,來(lái)分析一下最簡(jiǎn)的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是一個(gè)ELF格式32位小端(Little Endian)的可執(zhí)行文件,動(dòng)態(tài)鏈接并且符號(hào)表沒有去除。這正是Unix/Linux平臺(tái)典型的可執(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ù)的上級(jí)調(diào)用函數(shù)的?;刂?/p>
0x08048311: mov %esp,%ebp ---> esp值賦給ebp,設(shè)置main函數(shù)的棧基址
0x08048313: sub
0x08048316: and
c語(yǔ)言函數(shù)調(diào)用過程
c語(yǔ)言函數(shù)調(diào)用過程
c語(yǔ)言函數(shù)你知道多少?它的調(diào)用過程你了解嗎?下面學(xué)習(xí)啦小編為大家介紹一下c語(yǔ)言函數(shù),希望對(duì)你有幫助。
c語(yǔ)言函數(shù)編譯環(huán)境
OS: Axianux 1.0
Compiler: gcc 3..2.3
Linker: Solaris Link Editors 5.x
Debug Tool: gdb
Editor: vi
c語(yǔ)言函數(shù)最簡(jiǎn)C代碼分析
為簡(jiǎn)化問題,來(lái)分析一下最簡(jiǎn)的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是一個(gè)ELF格式32位小端(Little Endian)的可執(zhí)行文件,動(dòng)態(tài)鏈接并且符號(hào)表沒有去除。這正是Unix/Linux平臺(tái)典型的可執(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ù)的上級(jí)調(diào)用函數(shù)的棧基地址
0x08048311: mov %esp,%ebp ---> esp值賦給ebp,設(shè)置main函數(shù)的?;?/p>
0x08048313: sub
0x08048319: mov
c語(yǔ)言函數(shù)調(diào)用過程
c語(yǔ)言函數(shù)調(diào)用過程
c語(yǔ)言函數(shù)你知道多少?它的調(diào)用過程你了解嗎?下面學(xué)習(xí)啦小編為大家介紹一下c語(yǔ)言函數(shù),希望對(duì)你有幫助。
c語(yǔ)言函數(shù)編譯環(huán)境
OS: Axianux 1.0
Compiler: gcc 3..2.3
Linker: Solaris Link Editors 5.x
Debug Tool: gdb
Editor: vi
c語(yǔ)言函數(shù)最簡(jiǎn)C代碼分析
為簡(jiǎn)化問題,來(lái)分析一下最簡(jiǎn)的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是一個(gè)ELF格式32位小端(Little Endian)的可執(zhí)行文件,動(dòng)態(tài)鏈接并且符號(hào)表沒有去除。這正是Unix/Linux平臺(tái)典型的可執(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ù)的上級(jí)調(diào)用函數(shù)的?;刂?/p>
0x08048311: mov %esp,%ebp ---> esp值賦給ebp,設(shè)置main函數(shù)的?;?/p>
0x08048313: sub
0x0804831e: sub %eax,%esp ---> 無(wú)意義
0x08048320: mov
c語(yǔ)言函數(shù)調(diào)用過程
c語(yǔ)言函數(shù)調(diào)用過程
c語(yǔ)言函數(shù)你知道多少?它的調(diào)用過程你了解嗎?下面學(xué)習(xí)啦小編為大家介紹一下c語(yǔ)言函數(shù),希望對(duì)你有幫助。
c語(yǔ)言函數(shù)編譯環(huán)境
OS: Axianux 1.0
Compiler: gcc 3..2.3
Linker: Solaris Link Editors 5.x
Debug Tool: gdb
Editor: vi
c語(yǔ)言函數(shù)最簡(jiǎn)C代碼分析
為簡(jiǎn)化問題,來(lái)分析一下最簡(jiǎn)的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是一個(gè)ELF格式32位小端(Little Endian)的可執(zhí)行文件,動(dòng)態(tài)鏈接并且符號(hào)表沒有去除。這正是Unix/Linux平臺(tái)典型的可執(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ù)的上級(jí)調(diào)用函數(shù)的?;刂?/p>
0x08048311: mov %esp,%ebp ---> esp值賦給ebp,設(shè)置main函數(shù)的棧基址
0x08048313: sub
0x08048325: leave --->將ebp值賦給esp,pop先前棧內(nèi)的上級(jí)函數(shù)棧的基地址給ebp,恢復(fù)原?;?
0x08048326: ret ---> main函數(shù)返回,回到上級(jí)調(diào)用.
0x08048327: nop
End of assembler dump.
注:這里得到的匯編語(yǔ)言語(yǔ)法格式與Intel的手冊(cè)有很大不同,Unix/Linux采用AT&T匯編格式作為匯編語(yǔ)言的語(yǔ)法格式,如果想了解AT&T匯編可以參考文章 Linux 匯編語(yǔ)言開發(fā)指南.
問題一:誰(shuí)調(diào)用了 main函數(shù)?
在C語(yǔ)言的層面來(lái)看,main函數(shù)是一個(gè)程序的起始入口點(diǎn),而實(shí)際上,ELF可執(zhí)行文件的入口點(diǎn)并不是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語(yǔ)言函數(shù)調(diào)用過程
c語(yǔ)言函數(shù)調(diào)用過程
c語(yǔ)言函數(shù)你知道多少?它的調(diào)用過程你了解嗎?下面學(xué)習(xí)啦小編為大家介紹一下c語(yǔ)言函數(shù),希望對(duì)你有幫助。
c語(yǔ)言函數(shù)編譯環(huán)境
OS: Axianux 1.0
Compiler: gcc 3..2.3
Linker: Solaris Link Editors 5.x
Debug Tool: gdb
Editor: vi
c語(yǔ)言函數(shù)最簡(jiǎn)C代碼分析
為簡(jiǎn)化問題,來(lái)分析一下最簡(jiǎn)的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是一個(gè)ELF格式32位小端(Little Endian)的可執(zhí)行文件,動(dòng)態(tài)鏈接并且符號(hào)表沒有去除。這正是Unix/Linux平臺(tái)典型的可執(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ù)的上級(jí)調(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語(yǔ)言函數(shù)調(diào)用過程
c語(yǔ)言函數(shù)調(diào)用過程
c語(yǔ)言函數(shù)你知道多少?它的調(diào)用過程你了解嗎?下面學(xué)習(xí)啦小編為大家介紹一下c語(yǔ)言函數(shù),希望對(duì)你有幫助。
c語(yǔ)言函數(shù)編譯環(huán)境
OS: Axianux 1.0
Compiler: gcc 3..2.3
Linker: Solaris Link Editors 5.x
Debug Tool: gdb
Editor: vi
c語(yǔ)言函數(shù)最簡(jiǎn)C代碼分析
為簡(jiǎn)化問題,來(lái)分析一下最簡(jiǎn)的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是一個(gè)ELF格式32位小端(Little Endian)的可執(zhí)行文件,動(dòng)態(tài)鏈接并且符號(hào)表沒有去除。這正是Unix/Linux平臺(tái)典型的可執(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ù)的上級(jí)調(diào)用函數(shù)的?;刂?/p>
0x08048311: mov %esp,%ebp ---> esp值賦給ebp,設(shè)置main函數(shù)的?;?/p>
0x08048313: sub
0x08048274 <_start+16>: push
c語(yǔ)言函數(shù)調(diào)用過程
c語(yǔ)言函數(shù)調(diào)用過程
c語(yǔ)言函數(shù)你知道多少?它的調(diào)用過程你了解嗎?下面學(xué)習(xí)啦小編為大家介紹一下c語(yǔ)言函數(shù),希望對(duì)你有幫助。
c語(yǔ)言函數(shù)編譯環(huán)境
OS: Axianux 1.0
Compiler: gcc 3..2.3
Linker: Solaris Link Editors 5.x
Debug Tool: gdb
Editor: vi
c語(yǔ)言函數(shù)最簡(jiǎn)C代碼分析
為簡(jiǎn)化問題,來(lái)分析一下最簡(jiǎn)的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是一個(gè)ELF格式32位小端(Little Endian)的可執(zhí)行文件,動(dòng)態(tài)鏈接并且符號(hào)表沒有去除。這正是Unix/Linux平臺(tái)典型的可執(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ù)的上級(jí)調(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語(yǔ)言函數(shù)調(diào)用過程
c語(yǔ)言函數(shù)調(diào)用過程
c語(yǔ)言函數(shù)你知道多少?它的調(diào)用過程你了解嗎?下面學(xué)習(xí)啦小編為大家介紹一下c語(yǔ)言函數(shù),希望對(duì)你有幫助。
c語(yǔ)言函數(shù)編譯環(huán)境
OS: Axianux 1.0
Compiler: gcc 3..2.3
Linker: Solaris Link Editors 5.x
Debug Tool: gdb
Editor: vi
c語(yǔ)言函數(shù)最簡(jiǎn)C代碼分析
為簡(jiǎn)化問題,來(lái)分析一下最簡(jiǎn)的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是一個(gè)ELF格式32位小端(Little Endian)的可執(zhí)行文件,動(dòng)態(tài)鏈接并且符號(hào)表沒有去除。這正是Unix/Linux平臺(tái)典型的可執(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ù)的上級(jí)調(diào)用函數(shù)的棧基地址
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ù)返回值?
實(shí)際上IA32并沒有規(guī)定用哪個(gè)寄存器來(lái)保存返回值。但是,如果反匯編Solaris/Linux的二進(jìn)制文件,就會(huì)發(fā)現(xiàn),都用EAX保存函數(shù)返回值。
這不是偶然現(xiàn)象,是操作系統(tǒng)的ABI(Application Binary Interface)來(lái)決定的。
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的棧是用來(lái)存放臨時(shí)數(shù)據(jù),而且是LIFO,即后進(jìn)先出的。棧的增長(zhǎng)方向是從高地址向低地址增長(zhǎng),按字節(jié)為單位編址。
2) EBP是?;返闹羔槪肋h(yuǎn)指向棧底(高地址),ESP是棧指針,永遠(yuǎn)指向棧頂(低地址)。
3) PUSH一個(gè)long型數(shù)據(jù)時(shí),以字節(jié)為單位將數(shù)據(jù)壓入棧,從高到低按字節(jié)依次將數(shù)據(jù)存入ESP-1、ESP-2、ESP-3、ESP-4的地址單元。
4) POP一個(gè)long型數(shù)據(jù),過程與PUSH相反,依次將ESP-4、ESP-3、ESP-2、ESP-1從棧內(nèi)彈出,放入一個(gè)32位寄存器。
5) CALL指令用來(lái)調(diào)用一個(gè)函數(shù)或過程,此時(shí),下一條指令地址會(huì)被壓入堆棧,以備返回時(shí)能恢復(fù)執(zhí)行下條指令。
6) RET指令用來(lái)從一個(gè)函數(shù)或過程返回,之前CALL保存的下條指令地址會(huì)從棧內(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
原來(lái)編譯器會(huì)自動(dòng)在函數(shù)入口和出口處插入創(chuàng)建和釋放棧框架的語(yǔ)句。
函數(shù)被調(diào)用時(shí):
1) EIP/EBP成為新函數(shù)棧的邊界
函數(shù)被調(diào)用時(shí),返回時(shí)的EIP首先被壓入堆棧;創(chuàng)建??蚣軙r(shí),上級(jí)函數(shù)棧的EBP被壓入堆棧,與EIP一道行成新函數(shù)??蚣艿倪吔?。
2) EBP成為棧幀指針STP,用來(lái)指示新函數(shù)棧的邊界
棧幀建立后,EBP指向的棧的內(nèi)容就是上一級(jí)函數(shù)棧的EBP,可以想象,通過EBP就可以把層層調(diào)用函數(shù)的棧都回朔遍歷一遍,調(diào)試器就是利用這個(gè)特性實(shí)現(xiàn)backtrace功能的。
3) ESP總是作為棧指針指向棧頂,用來(lái)分配??臻g
棧分配空間給函數(shù)局部變量時(shí)的語(yǔ)句通常就是給ESP減去一個(gè)常數(shù)值,例如,分配一個(gè)整型數(shù)據(jù)就是 ESP-4。
4) 函數(shù)的參數(shù)傳遞和局部變量訪問可以通過STP即EBP來(lái)實(shí)現(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 (上級(jí)函數(shù)返回地址) | +----------------------+ +--> | EBP (上級(jí)函數(shù)的EBP) | --+ <------ 當(dāng)前函數(shù)A的EBP (即STP框架指針) | +----------------------+ +-->偏移量A | | Local Variables | | | | .......... | --+ <------ ESP指向函數(shù)A新分配的局部變量,局部變量可以通過A的ebp-偏移量A訪問 | f +----------------------+ | r | Arg n(函數(shù)B的第n個(gè)參數(shù)) | | a +----------------------+ | m | Arg .(函數(shù)B的第.個(gè)參數(shù)) | | e +----------------------+ | | Arg 1(函數(shù)B的第1個(gè)參數(shù)) | | o +----------------------+ | f | Arg 0(函數(shù)B的第0個(gè)參數(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個(gè)參數(shù)) | | +----------------------+ | | Arg .(函數(shù)C的第.個(gè)參數(shù)) | | +----------------------+ +--> frame of B | Arg 1(函數(shù)C的第1個(gè)參數(shù)) | | +----------------------+ | | Arg 0(函數(shù)C的第0個(gè)參數(shù)) | | +----------------------+ | | EIP (B函數(shù)的返回地址) | | +----------------------+ | +--> | EBP (B函數(shù)的EBP) |---+ <------ 當(dāng)前函數(shù)C的EBP (即STP框架指針) | +----------------------+ | | Local Variables | | | .......... | <------ ESP指向函數(shù)C新分配的局部變量 | +----------------------+----> 低地址frame of C
概念四:Stack aligned 棧對(duì)齊
那么,以下語(yǔ)句到底是和作用呢?
subl ,%esp
andl
c語(yǔ)言函數(shù)調(diào)用過程
c語(yǔ)言函數(shù)調(diào)用過程
c語(yǔ)言函數(shù)你知道多少?它的調(diào)用過程你了解嗎?下面學(xué)習(xí)啦小編為大家介紹一下c語(yǔ)言函數(shù),希望對(duì)你有幫助。
c語(yǔ)言函數(shù)編譯環(huán)境
OS: Axianux 1.0
Compiler: gcc 3..2.3
Linker: Solaris Link Editors 5.x
Debug Tool: gdb
Editor: vi
c語(yǔ)言函數(shù)最簡(jiǎn)C代碼分析
為簡(jiǎn)化問題,來(lái)分析一下最簡(jiǎn)的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是一個(gè)ELF格式32位小端(Little Endian)的可執(zhí)行文件,動(dòng)態(tài)鏈接并且符號(hào)表沒有去除。這正是Unix/Linux平臺(tái)典型的可執(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ù)的上級(jí)調(diào)用函數(shù)的?;刂?/p>
0x08048311: mov %esp,%ebp ---> esp值賦給ebp,設(shè)置main函數(shù)的?;?/p>
0x08048313: sub
表面來(lái)看,這條語(yǔ)句最直接的后果是使ESP的地址后4位為0,即16字節(jié)對(duì)齊,那么為什么這么做呢?
原來(lái),IA32 系列CPU的一些指令分別在4、8、16字節(jié)對(duì)齊時(shí)會(huì)有更加的運(yùn)行速度,因此gcc編譯器為提高生成代碼在IA32上的運(yùn)行速度,默認(rèn)對(duì)產(chǎn)生的代碼進(jìn)行16字節(jié)對(duì)齊.
andl
c語(yǔ)言函數(shù)調(diào)用過程
c語(yǔ)言函數(shù)調(diào)用過程
c語(yǔ)言函數(shù)你知道多少?它的調(diào)用過程你了解嗎?下面學(xué)習(xí)啦小編為大家介紹一下c語(yǔ)言函數(shù),希望對(duì)你有幫助。
c語(yǔ)言函數(shù)編譯環(huán)境
OS: Axianux 1.0
Compiler: gcc 3..2.3
Linker: Solaris Link Editors 5.x
Debug Tool: gdb
Editor: vi
c語(yǔ)言函數(shù)最簡(jiǎn)C代碼分析
為簡(jiǎn)化問題,來(lái)分析一下最簡(jiǎn)的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是一個(gè)ELF格式32位小端(Little Endian)的可執(zhí)行文件,動(dòng)態(tài)鏈接并且符號(hào)表沒有去除。這正是Unix/Linux平臺(tái)典型的可執(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ù)的上級(jí)調(diào)用函數(shù)的?;刂?/p>
0x08048311: mov %esp,%ebp ---> esp值賦給ebp,設(shè)置main函數(shù)的?;?/p>
0x08048313: sub
如果查一下gcc的手冊(cè),就會(huì)發(fā)現(xiàn)關(guān)于棧對(duì)齊的參數(shù)設(shè)置:
-mpreferred-stack-boundary=n ---> 希望棧按照2的n次的字節(jié)邊界對(duì)齊, n的取值范圍是2-12.
默認(rèn)情況下,n是等于4的,也就是說(shuō),默認(rèn)情況下,gcc是16字節(jié)對(duì)齊,以適應(yīng)IA32大多數(shù)指令的要求。
讓我們利用-mpreferred-stack-boundary=2來(lái)去除棧對(duì)齊指令:
(gdb) disass main
Dump of assembler code for function main:
0x08048310: push %ebp
0x08048311: mov %esp,%ebp
0x08048313: mov
c語(yǔ)言函數(shù)調(diào)用過程
c語(yǔ)言函數(shù)調(diào)用過程
c語(yǔ)言函數(shù)你知道多少?它的調(diào)用過程你了解嗎?下面學(xué)習(xí)啦小編為大家介紹一下c語(yǔ)言函數(shù),希望對(duì)你有幫助。
c語(yǔ)言函數(shù)編譯環(huán)境
OS: Axianux 1.0
Compiler: gcc 3..2.3
Linker: Solaris Link Editors 5.x
Debug Tool: gdb
Editor: vi
c語(yǔ)言函數(shù)最簡(jiǎn)C代碼分析
為簡(jiǎn)化問題,來(lái)分析一下最簡(jiǎn)的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是一個(gè)ELF格式32位小端(Little Endian)的可執(zhí)行文件,動(dòng)態(tài)鏈接并且符號(hào)表沒有去除。這正是Unix/Linux平臺(tái)典型的可執(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ù)的上級(jí)調(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.
可以看到,棧對(duì)齊指令沒有了,因?yàn)?,IA32的棧本身就是4字節(jié)對(duì)齊的,不需要用額外指令進(jìn)行對(duì)齊。
問題五:棧框架指針STP是不是必須的呢?
[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語(yǔ)言函數(shù)調(diào)用過程
c語(yǔ)言函數(shù)調(diào)用過程
c語(yǔ)言函數(shù)你知道多少?它的調(diào)用過程你了解嗎?下面學(xué)習(xí)啦小編為大家介紹一下c語(yǔ)言函數(shù),希望對(duì)你有幫助。
c語(yǔ)言函數(shù)編譯環(huán)境
OS: Axianux 1.0
Compiler: gcc 3..2.3
Linker: Solaris Link Editors 5.x
Debug Tool: gdb
Editor: vi
c語(yǔ)言函數(shù)最簡(jiǎn)C代碼分析
為簡(jiǎn)化問題,來(lái)分析一下最簡(jiǎn)的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是一個(gè)ELF格式32位小端(Little Endian)的可執(zhí)行文件,動(dòng)態(tài)鏈接并且符號(hào)表沒有去除。這正是Unix/Linux平臺(tái)典型的可執(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ù)的上級(jí)調(diào)用函數(shù)的棧基地址
0x08048311: mov %esp,%ebp ---> esp值賦給ebp,設(shè)置main函數(shù)的棧基址
0x08048313: sub
0x08048315: ret
0x08048316: nop
0x08048317: nop
End of assembler dump.
由此可知,-fomit-frame-pointer 可以去除STP。
去除STP后有什么缺點(diǎn)呢?
1)增加調(diào)式難度
由于STP在調(diào)試器backtrace的指令中被使用到,因此沒有STP該調(diào)試指令就無(wú)法使用。
2)降低匯編代碼可讀性
函數(shù)參數(shù)和局部變量的訪問,在沒有ebp的情況下,都只能通過+xx(esp)的方式訪問,而很難區(qū)分兩種方式,降低了程序的可讀性。
去除STP有什么優(yōu)點(diǎn)呢?
1)節(jié)省??臻g。
2)減少建立和撤銷??蚣艿闹噶詈?,簡(jiǎn)化了代碼。
3)使ebp空閑出來(lái),使之作為通用寄存器使用,增加通用寄存器的數(shù)量
4)以上3點(diǎn)使得程序運(yùn)行速度更快。
概念六:Calling Convention 調(diào)用約定和ABI (Application Binary Interface) 應(yīng)用程序二進(jìn)制接口。
函數(shù)如何找到它的參數(shù)?
函數(shù)如何返回結(jié)果?
函數(shù)在哪里存放局部變量?
哪一個(gè)硬件寄存器是起始空間?
哪一個(gè)硬件寄存器必須預(yù)先保留?
Calling Convention 調(diào)用約定對(duì)以上問題作出了規(guī)定。Calling Convention也是ABI的一部分。因此,遵守相同ABI規(guī)范的操作系統(tǒng),使其相互間實(shí)現(xiàn)二進(jìn)制代碼的互操作成為了可能。
例如:由于Solaris、Linux都遵守System V的ABI,Solaris 10就提供了直接運(yùn)行Linux二進(jìn)制程序的功能。
c語(yǔ)言函數(shù)小結(jié)
本文通過最簡(jiǎn)的C程序,引出以下概念:
STP ??蚣苤羔?/p>
Stack aligned 棧對(duì)齊
Calling Convention 調(diào)用約定 和 ABI (Application Binary Interface) 應(yīng)用程序二進(jìn)制接口
看了“c語(yǔ)言函數(shù)調(diào)用過程”的人還看了: