1.被分析的C程序
#include <stdio.h>
#include <stdarg.h>
int
test1(int a1,int b1)
{
int c1;
c1 = a1+b1;
return c1;
}
int
test2(int a2,int a3)
{
int c1 = 0 ,c2;
c2 = test1(a2,a3);
return c1;
}
int
test3(int n_val,...)
{
va_list var_arg;
int i,c;
va_start(var_arg,n_val);
for(i=0;i<n_val;i++)
{
c = va_arg(var_arg,int);
printf("arg%d=%d\n",i,c);
}
va_end(var_arg);
}
int
main(int argc,char **argv)
{
int main_c;
int x=12,y=1,z=3;
main_c = test2(10,20);
test3(1,2,3,4,5,6,7,8,9,10,11);
// test3(3,110,1,2,3,4,5,6,7,8,9,12,154,12);
// test3(7,x++,x++,x++,x++,x++,x++,x++);
// test3(1,2,3);
return main_c;
}
2.通過arm-linux-gcc得到可執行文件test.out
/*
通過命令:arm-linux-objdump -d test.out > func.txt 得到反彙編文件;
結合本文最下面給出的相關文檔鏈接中的 “典型的存儲空間安排” 去看,可以知道以下各指令依次存儲在正文段中。
*/
/*
在對彙編進行分析之前,我們首先簡單介紹一下基本的彙編命令
*/
fp:棧底寄存器
sp:棧頂寄存器
ldr r0, [pc,#4] ; 把pc+4內存地址的值給r0
str r1, [pc,#4] ; 把r1的值寫入pc+4內存地址
push,pop
lr:鏈接地址寄存器,存放下一條執行指令
/*
下面我們摘取最熟悉的main函數進行分析
*/
000084f8 <test1>:
84f8: e52db004 push {fp} ; (str fp, [sp, #-4]!)
84fc: e28db000 add fp, sp, #0
8500: e24dd014 sub sp, sp, #20
8504: e50b0010 str r0, [fp, #-16]
8508: e50b1014 str r1, [fp, #-20]
850c: e51b2010 ldr r2, [fp, #-16]
8510: e51b3014 ldr r3, [fp, #-20]
8514: e0823003 add r3, r2, r3
8518: e50b3008 str r3, [fp, #-8]
851c: e51b3008 ldr r3, [fp, #-8]
8520: e1a00003 mov r0, r3
8524: e28bd000 add sp, fp, #0
8528: e8bd0800 pop {fp}
852c: e12fff1e bx lr
00008530 <test2>:
8530: e92d4800 push {fp, lr}
8534: e28db004 add fp, sp, #4
8538: e24dd010 sub sp, sp, #16
853c: e50b0010 str r0, [fp, #-16]
8540: e50b1014 str r1, [fp, #-20]
8544: e3a03000 mov r3, #0
8548: e50b3008 str r3, [fp, #-8]
854c: e51b0010 ldr r0, [fp, #-16]
8550: e51b1014 ldr r1, [fp, #-20]
8554: ebffffe7 bl 84f8 <test1>
8558: e50b000c str r0, [fp, #-12]
855c: e51b3008 ldr r3, [fp, #-8]
8560: e1a00003 mov r0, r3
8564: e24bd004 sub sp, fp, #4
8568: e8bd8800 pop {fp, pc}
0000856c <test3>:
856c: e92d000f push {r0, r1, r2, r3}
8570: e92d4800 push {fp, lr}
8574: e28db004 add fp, sp, #4
8578: e24dd010 sub sp, sp, #16
857c: e28b3008 add r3, fp, #8
8580: e50b3010 str r3, [fp, #-16]
8584: e3a03000 mov r3, #0
8588: e50b3008 str r3, [fp, #-8]
858c: ea00000c b 85c4 <test3+0x58>
8590: e51b3010 ldr r3, [fp, #-16]
8594: e2832004 add r2, r3, #4
8598: e50b2010 str r2, [fp, #-16]
859c: e5933000 ldr r3, [r3]
85a0: e50b300c str r3, [fp, #-12]
85a4: e3080690 movw r0, #34448 ; 0x8690
85a8: e3400000 movt r0, #0
85ac: e51b1008 ldr r1, [fp, #-8]
85b0: e51b200c ldr r2, [fp, #-12]
85b4: ebffff6b bl 8368 <_init+0x24>
85b8: e51b3008 ldr r3, [fp, #-8]
85bc: e2833001 add r3, r3, #1
85c0: e50b3008 str r3, [fp, #-8]
85c4: e51b2008 ldr r2, [fp, #-8]
85c8: e59b3004 ldr r3, [fp, #4]
85cc: e1520003 cmp r2, r3
85d0: baffffee blt 8590 <test3+0x24>
85d4: e1a00003 mov r0, r3
85d8: e24bd004 sub sp, fp, #4
85dc: e8bd4800 pop {fp, lr}
85e0: e28dd010 add sp, sp, #16
85e4: e12fff1e bx lr
000085e8 <main>:
85e8: e92d4800 push {fp, lr}
85ec: e28db004 add fp, sp, #4
85f0: e24dd038 sub sp, sp, #56 ; 0x38
85f4: e50b0018 str r0, [fp, #-24]
85f8: e50b101c str r1, [fp, #-28]
85fc: e3a0300c mov r3, #12
8600: e50b3008 str r3, [fp, #-8]
8604: e3a03001 mov r3, #1
8608: e50b300c str r3, [fp, #-12]
860c: e3a03003 mov r3, #3
8610: e50b3010 str r3, [fp, #-16]
8614: e3a0000a mov r0, #10
8618: e3a01014 mov r1, #20
861c: ebffffc3 bl 8530 <test2>
8620: e50b0014 str r0, [fp, #-20]
8624: e3a03005 mov r3, #5
8628: e58d3000 str r3, [sp]
862c: e3a03006 mov r3, #6
8630: e58d3004 str r3, [sp, #4]
8634: e3a03007 mov r3, #7
8638: e58d3008 str r3, [sp, #8]
863c: e3a03008 mov r3, #8
8640: e58d300c str r3, [sp, #12]
8644: e3a03009 mov r3, #9
8648: e58d3010 str r3, [sp, #16]
864c: e3a0300a mov r3, #10
8650: e58d3014 str r3, [sp, #20]
8654: e3a0300b mov r3, #11
8658: e58d3018 str r3, [sp, #24]
865c: e3a00001 mov r0, #1
8660: e3a01002 mov r1, #2
8664: e3a02003 mov r2, #3
8668: e3a03004 mov r3, #4
866c: ebffffbe bl 856c <test3>
8670: e51b3014 ldr r3, [fp, #-20]
8674: e1a00003 mov r0, r3
8678: e24bd004 sub sp, fp, #4
867c: e8bd8800 pop {fp, pc}
test.out: file format elf32-littlearm
Disassembly of section .init:
00008344 <_init>:
8344: e1a0c00d mov ip, sp
8348: e92ddff0 push {r4, r5, r6, r7, r8, r9, sl, fp, ip, lr, pc}
834c: e24cb004 sub fp, ip, #4
8350: e91baff0 ldmdb fp, {r4, r5, r6, r7, r8, r9, sl, fp, sp, pc}
Disassembly of section .plt:
00008354 <.plt>:
8354: e52de004 push {lr} ; (str lr, [sp, #-4]!)
8358: e59fe004 ldr lr, [pc, #4] ; 8364 <_init+0x20>
835c: e08fe00e add lr, pc, lr
8360: e5bef008 ldr pc, [lr, #8]!
8364: 00008418 .word 0x00008418
8368: e28fc600 add ip, pc, #0
836c: e28cca08 add ip, ip, #32768 ; 0x8000
8370: e5bcf418 ldr pc, [ip, #1048]! ; 0x418
8374: e28fc600 add ip, pc, #0
8378: e28cca08 add ip, ip, #32768 ; 0x8000
837c: e5bcf410 ldr pc, [ip, #1040]! ; 0x410
8380: e28fc600 add ip, pc, #0
8384: e28cca08 add ip, ip, #32768 ; 0x8000
8388: e5bcf408 ldr pc, [ip, #1032]! ; 0x408
838c: e28fc600 add ip, pc, #0
8390: e28cca08 add ip, ip, #32768 ; 0x8000
8394: e5bcf400 ldr pc, [ip, #1024]! ; 0x400
8398: e28fc600 add ip, pc, #0
839c: e28cca08 add ip, ip, #32768 ; 0x8000
83a0: e5bcf3f8 ldr pc, [ip, #1016]! ; 0x3f8
Disassembly of section .text:
000083a4 <_start>:
83a4: e3a0b000 .word 0xe3a0b000
83a8: e3a0e000 .word 0xe3a0e000
83ac: e49d1004 .word 0xe49d1004
83b0: e1a0200d .word 0xe1a0200d
83b4: e52d2004 .word 0xe52d2004
83b8: e52d0004 .word 0xe52d0004
83bc: e59fc010 .word 0xe59fc010
83c0: e52dc004 .word 0xe52dc004
83c4: e59f000c .word 0xe59f000c
83c8: e59f300c .word 0xe59f300c
83cc: eaffffee .word 0xeaffffee
83d0: ebffffe7 .word 0xebffffe7
83d4: 00008680 .word 0x00008680
83d8: 000085e8 .word 0x000085e8
83dc: 00008344 .word 0x00008344
000083e0 <deregister_tm_clones>:
83e0: e92d4008 push {r3, lr}
83e4: e59f0020 ldr r0, [pc, #32] ; 840c <deregister_tm_clones+0x2c>
83e8: e59f3020 ldr r3, [pc, #32] ; 8410 <deregister_tm_clones+0x30>
83ec: e0603003 rsb r3, r0, r3
83f0: e3530006 cmp r3, #6
83f4: 98bd8008 popls {r3, pc}
83f8: e59f3014 ldr r3, [pc, #20] ; 8414 <deregister_tm_clones+0x34>
83fc: e3530000 cmp r3, #0
8400: 08bd8008 popeq {r3, pc}
8404: e12fff33 blx r3
8408: e8bd8008 pop {r3, pc}
840c: 000107a4 .word 0x000107a4
8410: 000107a7 .word 0x000107a7
8414: 00000000 .word 0x00000000
00008418 <register_tm_clones>:
8418: e59f002c ldr r0, [pc, #44] ; 844c <register_tm_clones+0x34>
841c: e59f102c ldr r1, [pc, #44] ; 8450 <register_tm_clones+0x38>
8420: e92d4008 push {r3, lr}
8424: e0601001 rsb r1, r0, r1
8428: e1a01141 asr r1, r1, #2
842c: e0811fa1 add r1, r1, r1, lsr #31
8430: e1b010c1 asrs r1, r1, #1
8434: 08bd8008 popeq {r3, pc}
8438: e59f3014 ldr r3, [pc, #20] ; 8454 <register_tm_clones+0x3c>
843c: e3530000 cmp r3, #0
8440: 08bd8008 popeq {r3, pc}
8444: e12fff33 blx r3
8448: e8bd8008 pop {r3, pc}
844c: 000107a4 .word 0x000107a4
8450: 000107a4 .word 0x000107a4
8454: 00000000 .word 0x00000000
00008458 <__do_global_dtors_aux>:
8458: e59f3034 ldr r3, [pc, #52] ; 8494 <__do_global_dtors_aux+0x3c>
845c: e92d4010 push {r4, lr}
8460: e1a04003 mov r4, r3
8464: e5d32000 ldrb r2, [r3]
8468: e3520000 cmp r2, #0
846c: 18bd8010 popne {r4, pc}
8470: ebffffda bl 83e0 <deregister_tm_clones>
8474: e59f301c ldr r3, [pc, #28] ; 8498 <__do_global_dtors_aux+0x40>
8478: e3530000 cmp r3, #0
847c: 0a000001 beq 8488 <__do_global_dtors_aux+0x30>
8480: e59f0014 ldr r0, [pc, #20] ; 849c <__do_global_dtors_aux+0x44>
8484: ebffffbd bl 8380 <_init+0x3c>
8488: e3a03001 mov r3, #1
848c: e5c43000 strb r3, [r4]
8490: e8bd8010 pop {r4, pc}
8494: 000107a4 .word 0x000107a4
8498: 00000000 .word 0x00000000
849c: 0000869c .word 0x0000869c
000084a0 <frame_dummy>:
84a0: e92d4008 push {r3, lr}
84a4: e59f3038 ldr r3, [pc, #56] ; 84e4 <frame_dummy+0x44>
84a8: e3530000 cmp r3, #0
84ac: 0a000002 beq 84bc <frame_dummy+0x1c>
84b0: e59f0030 ldr r0, [pc, #48] ; 84e8 <frame_dummy+0x48>
84b4: e59f1030 ldr r1, [pc, #48] ; 84ec <frame_dummy+0x4c>
84b8: ebffffb6 bl 8398 <_init+0x54>
84bc: e59f002c ldr r0, [pc, #44] ; 84f0 <frame_dummy+0x50>
84c0: e5903000 ldr r3, [r0]
84c4: e3530000 cmp r3, #0
84c8: 0a000003 beq 84dc <frame_dummy+0x3c>
84cc: e59f3020 ldr r3, [pc, #32] ; 84f4 <frame_dummy+0x54>
84d0: e3530000 cmp r3, #0
84d4: 0a000000 beq 84dc <frame_dummy+0x3c>
84d8: e12fff33 blx r3
84dc: e8bd4008 pop {r3, lr}
84e0: eaffffcc b 8418 <register_tm_clones>
84e4: 00000000 .word 0x00000000
84e8: 0000869c .word 0x0000869c
84ec: 000107a8 .word 0x000107a8
84f0: 000106a8 .word 0x000106a8
84f4: 00000000 .word 0x00000000
000084f8 <test1>:
84f8: e52db004 push {fp} ; (str fp, [sp, #-4]!)
84fc: e28db000 add fp, sp, #0
8500: e24dd014 sub sp, sp, #20
8504: e50b0010 str r0, [fp, #-16]
8508: e50b1014 str r1, [fp, #-20]
850c: e51b2010 ldr r2, [fp, #-16]
8510: e51b3014 ldr r3, [fp, #-20]
8514: e0823003 add r3, r2, r3
8518: e50b3008 str r3, [fp, #-8]
851c: e51b3008 ldr r3, [fp, #-8]
8520: e1a00003 mov r0, r3
8524: e28bd000 add sp, fp, #0
8528: e8bd0800 pop {fp}
852c: e12fff1e bx lr
00008530 <test2>:
8530: e92d4800 push {fp, lr}
8534: e28db004 add fp, sp, #4
8538: e24dd010 sub sp, sp, #16
853c: e50b0010 str r0, [fp, #-16]
8540: e50b1014 str r1, [fp, #-20]
8544: e3a03000 mov r3, #0
8548: e50b3008 str r3, [fp, #-8]
854c: e51b0010 ldr r0, [fp, #-16]
8550: e51b1014 ldr r1, [fp, #-20]
8554: ebffffe7 bl 84f8 <test1>
8558: e50b000c str r0, [fp, #-12]
855c: e51b3008 ldr r3, [fp, #-8]
8560: e1a00003 mov r0, r3
8564: e24bd004 sub sp, fp, #4
8568: e8bd8800 pop {fp, pc}
0000856c <test3>:
856c: e92d000f push {r0, r1, r2, r3}
8570: e92d4800 push {fp, lr}
8574: e28db004 add fp, sp, #4
8578: e24dd010 sub sp, sp, #16
857c: e28b3008 add r3, fp, #8
8580: e50b3010 str r3, [fp, #-16]
8584: e3a03000 mov r3, #0
8588: e50b3008 str r3, [fp, #-8]
858c: ea00000c b 85c4 <test3+0x58>
8590: e51b3010 ldr r3, [fp, #-16]
8594: e2832004 add r2, r3, #4
8598: e50b2010 str r2, [fp, #-16]
859c: e5933000 ldr r3, [r3]
85a0: e50b300c str r3, [fp, #-12]
85a4: e3080690 movw r0, #34448 ; 0x8690
85a8: e3400000 movt r0, #0
85ac: e51b1008 ldr r1, [fp, #-8]
85b0: e51b200c ldr r2, [fp, #-12]
85b4: ebffff6b bl 8368 <_init+0x24>
85b8: e51b3008 ldr r3, [fp, #-8]
85bc: e2833001 add r3, r3, #1
85c0: e50b3008 str r3, [fp, #-8]
85c4: e51b2008 ldr r2, [fp, #-8]
85c8: e59b3004 ldr r3, [fp, #4]
85cc: e1520003 cmp r2, r3
85d0: baffffee blt 8590 <test3+0x24>
85d4: e1a00003 mov r0, r3
85d8: e24bd004 sub sp, fp, #4
85dc: e8bd4800 pop {fp, lr}
85e0: e28dd010 add sp, sp, #16
85e4: e12fff1e bx lr
000085e8 <main>:
85e8: e92d4800 push {fp, lr} //將fp、lr壓入棧中保存
//將fp指向當前棧頂+4,並使sp下偏,爲main函數開闢一段棧空間
85ec: e28db004 add fp, sp, #4
85f0: e24dd038 sub sp, sp, #56 ; 0x38
//下面兩句將main函數的兩個入參分別寫入內存,進行保存
85f4: e50b0018 str r0, [fp, #-24]
85f8: e50b101c str r1, [fp, #-28]
//保存局部變量
85fc: e3a0300c mov r3, #12
8600: e50b3008 str r3, [fp, #-8]
8604: e3a03001 mov r3, #1
8608: e50b300c str r3, [fp, #-12]
860c: e3a03003 mov r3, #3
8610: e50b3010 str r3, [fp, #-16]
/*
可以看到main函數即將調用子函數test2,爲此將做一些準備工作,包括:
1.將需要傳遞的參數從左向右依次存入對應的寄存器進行保存和傳遞;
2.使用bl指令,調用test2;
*/
8614: e3a0000a mov r0, #10
8618: e3a01014 mov r1, #20
861c: ebffffc3 bl 8530 <test2>
//將返回值寫入內存
8620: e50b0014 str r0, [fp, #-20]
/*
對於不定參函數來說,其參數個數無法確定,最開始無法直接分配
棧空間。當參數個數大於4個時,需要在已經分配棧空間的基礎上從
第4個參數開始壓棧,而前4個將依次保存在r0~r3寄存器中。
*/
8624: e3a03005 mov r3, #5
8628: e58d3000 str r3, [sp]
862c: e3a03006 mov r3, #6
8630: e58d3004 str r3, [sp, #4]
8634: e3a03007 mov r3, #7
8638: e58d3008 str r3, [sp, #8]
863c: e3a03008 mov r3, #8
8640: e58d300c str r3, [sp, #12]
8644: e3a03009 mov r3, #9
8648: e58d3010 str r3, [sp, #16]
864c: e3a0300a mov r3, #10
8650: e58d3014 str r3, [sp, #20]
8654: e3a0300b mov r3, #11
8658: e58d3018 str r3, [sp, #24]
865c: e3a00001 mov r0, #1
8660: e3a01002 mov r1, #2
8664: e3a02003 mov r2, #3
8668: e3a03004 mov r3, #4
866c: ebffffbe bl 856c <test3>
8670: e51b3014 ldr r3, [fp, #-20]
8674: e1a00003 mov r0, r3
8678: e24bd004 sub sp, fp, #4
867c: e8bd8800 pop {fp, pc}
3.總結
1.對於程序典型的存儲空間分佈有進一步的理解,可以知道反彙編出的,或者說經過編譯、鏈接後的C程序形成一條條的彙編指令(值得注意的是同樣的C程序,在不同的CPU架構由不同編譯器所得的結果是不一樣)。形成的彙編指令所在的內存地址也已經分配完畢,保存在正文段。
2.隨後,程序開始依照內存地址和機器指令一步步執行程序,通過以上分析,這裏我們重點總結函數嵌套調用過程中棧空間的變化情況。
3.從存儲空間分佈圖可以看到,棧空間是由高地址往低地址生長的。
4.調用函數(如main)調用被調用函數(如test2)前,都將做一些準備工作,主要是將參數存入r0~r3寄存器中。當參數多於4個時,其它參數將採用直接壓棧的方式。從被調用函數的彙編代碼來看,當參數多於4個時,r0~r3寄存器也將馬上被壓入棧中,而參數少於4個時就不壓棧,速度上來看要快一些。
5.當進入被調用函數彙編後,首先會將fp,lr等寄存器值壓棧,保存目前棧幀狀態以便恢復。隨後fp指向當前棧頂,而棧頂下偏一定量,fp、sp的差值即表示爲被調用函數開闢的棧空間。定義的局部變量也在開闢的棧空間內使用。隨後的一系列運算不再展開敘述。
4.相關文檔鏈接
程序典型的存儲空間安排圖:
http://blog.csdn.net/sinat_26551021/article/details/79052470
ARM彙編指令:
函數調用過程探究:
http://www.cnblogs.com/bangerlee/archive/2012/05/22/2508772.html
x86_64架構下函數調用過程分析:
http://blog.csdn.net/sinat_26551021/article/details/79052541
X86-64寄存器和棧幀: