您的位置:首页 > 运维架构 > 网站架构

x86_64架构下函数调用过程分析

2018-01-13 17:16 621 查看
//被分析的C程序
int
test1(int a1,int b1)
{
int c1;
c1 = a1+b1;
return c1;
}

int
test2(int a2,char b2)
{
int c2;
c2 = test1(30,40);
return c2;
}

int
main(int argc,char **argv)
{

int main_c;
int x=2,y=1,z=3;
main_c = test2(10,20);

return main_c;
}

//通过gcc得到可执行文件test.out

/*
通过命令:objdump -d test.out > func.txt 得到反汇编文件;
结合图1 “典型的存储空间安排” 去看,可以知道以下各指令依次存储在正文段中。
*/
test.out:     file format elf64-x86-64

Disassembly of section .init:

0000000000400390 <_init>:
400390:   48 83 ec 08             sub    $0x8,%rsp
400394:   48 8b 05 5d 0c 20 00    mov    0x200c5d(%rip),%rax        # 600ff8 <_DYNAMIC+0x1d0>
40039b:   48 85 c0                test   %rax,%rax
40039e:   74 05                   je     4003a5 <_init+0x15>
4003a0:   e8 2b 00 00 00          callq  4003d0 <__libc_start_main@plt+0x10>
4003a5:   48 83 c4 08             add    $0x8,%rsp
4003a9:   c3                      retq

Disassembly of section .plt:

00000000004003b0 <__libc_start_main@plt-0x10>:
4003b0:   ff 35 52 0c 20 00       pushq  0x200c52(%rip)        # 601008 <_GLOBAL_OFFSET_TABLE_+0x8>
4000

4003b6:   ff 25 54 0c 20 00       jmpq   *0x200c54(%rip)        # 601010 <_GLOBAL_OFFSET_TABLE_+0x10>
4003bc:   0f 1f 40 00             nopl   0x0(%rax)

00000000004003c0 <__libc_start_main@plt>:
4003c0:   ff 25 52 0c 20 00       jmpq   *0x200c52(%rip)        # 601018 <_GLOBAL_OFFSET_TABLE_+0x18>
4003c6:   68 00 00 00 00          pushq  $0x0
4003cb:   e9 e0 ff ff ff          jmpq   4003b0 <_init+0x20>

Disassembly of section .plt.got:

00000000004003d0 <.plt.got>:
4003d0:   ff 25 22 0c 20 00       jmpq   *0x200c22(%rip)        # 600ff8 <_DYNAMIC+0x1d0>
4003d6:   66 90                   xchg   %ax,%ax

Disassembly of section .text:

00000000004003e0 <_start>:
4003e0:   31 ed                   xor    %ebp,%ebp
4003e2:   49 89 d1                mov    %rdx,%r9
4003e5:   5e                      pop    %rsi
4003e6:   48 89 e2                mov    %rsp,%rdx
4003e9:   48 83 e4 f0             and    $0xfffffffffffffff0,%rsp
4003ed:   50                      push   %rax
4003ee:   54                      push   %rsp
4003ef:   49 c7 c0 d0 05 40 00    mov    $0x4005d0,%r8
4003f6:   48 c7 c1 60 05 40 00    mov    $0x400560,%rcx
4003fd:   48 c7 c7 17 05 40 00    mov    $0x400517,%rdi
400404:   e8 b7 ff ff ff          callq  4003c0 <__libc_start_main@plt>
400409:   f4                      hlt
40040a:   66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)

0000000000400410 <deregister_tm_clones>:
400410:   b8 37 10 60 00          mov    $0x601037,%eax
400415:   55                      push   %rbp
400416:   48 2d 30 10 60 00       sub    $0x601030,%rax
40041c:   48 83 f8 0e             cmp    $0xe,%rax
400420:   48 89 e5                mov    %rsp,%rbp
400423:   76 1b                   jbe    400440 <deregister_tm_clones+0x30>
400425:   b8 00 00 00 00          mov    $0x0,%eax
40042a:   48 85 c0                test   %rax,%rax
40042d:   74 11                   je     400440 <deregister_tm_clones+0x30>
40042f:   5d                      pop    %rbp
400430:   bf 30 10 60 00          mov    $0x601030,%edi
400435:   ff e0                   jmpq   *%rax
400437:   66 0f 1f 84 00 00 00    nopw   0x0(%rax,%rax,1)
40043e:   00 00
400440:   5d                      pop    %rbp
400441:   c3                      retq
400442:   0f 1f 40 00             nopl   0x0(%rax)
400446:   66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
40044d:   00 00 00

0000000000400450 <register_tm_clones>:
400450:   be 30 10 60 00          mov    $0x601030,%esi
400455:   55                      push   %rbp
400456:   48 81 ee 30 10 60 00    sub    $0x601030,%rsi
40045d:   48 c1 fe 03             sar    $0x3,%rsi
400461:   48 89 e5                mov    %rsp,%rbp
400464:   48 89 f0                mov    %rsi,%rax
400467:   48 c1 e8 3f             shr    $0x3f,%rax
40046b:   48 01 c6                add    %rax,%rsi
40046e:   48 d1 fe                sar    %rsi
400471:   74 15                   je     400488 <register_tm_clones+0x38>
400473:   b8 00 00 00 00          mov    $0x0,%eax
400478:   48 85 c0                test   %rax,%rax
40047b:   74 0b                   je     400488 <register_tm_clones+0x38>
40047d:   5d                      pop    %rbp
40047e:   bf 30 10 60 00          mov    $0x601030,%edi
400483:   ff e0                   jmpq   *%rax
400485:   0f 1f 00                nopl   (%rax)
400488:   5d                      pop    %rbp
400489:   c3                      retq
40048a:   66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)

0000000000400490 <__do_global_dtors_aux>:
400490:   80 3d 99 0b 20 00 00    cmpb   $0x0,0x200b99(%rip)        # 601030 <__TMC_END__>
400497:   75 11                   jne    4004aa <__do_global_dtors_aux+0x1a>
400499:   55                      push   %rbp
40049a:   48 89 e5                mov    %rsp,%rbp
40049d:   e8 6e ff ff ff          callq  400410 <deregister_tm_clones>
4004a2:   5d                      pop    %rbp
4004a
13c62
3:   c6 05 86 0b 20 00 01    movb   $0x1,0x200b86(%rip)        # 601030 <__TMC_END__>
4004aa:   f3 c3                   repz retq
4004ac:   0f 1f 40 00             nopl   0x0(%rax)

00000000004004b0 <frame_dummy>:
4004b0:   bf 20 0e 60 00          mov    $0x600e20,%edi
4004b5:   48 83 3f 00             cmpq   $0x0,(%rdi)
4004b9:   75 05                   jne    4004c0 <frame_dummy+0x10>
4004bb:   eb 93                   jmp    400450 <register_tm_clones>
4004bd:   0f 1f 00                nopl   (%rax)
4004c0:   b8 00 00 00 00          mov    $0x0,%eax
4004c5:   48 85 c0                test   %rax,%rax
4004c8:   74 f1                   je     4004bb <frame_dummy+0xb>
4004ca:   55                      push   %rbp
4004cb:   48 89 e5                mov    %rsp,%rbp
4004ce:   ff d0                   callq  *%rax
4004d0:   5d                      pop    %rbp
4004d1:   e9 7a ff ff ff          jmpq   400450 <register_tm_clones>

00000000004004d6 <test1>:
4004d6:   55                      push   %rbp
4004d7:   48 89 e5                mov    %rsp,%rbp
4004da:   89 7d ec                mov    %edi,-0x14(%rbp)
4004dd:   89 75 e8                mov    %esi,-0x18(%rbp)
4004e0:   8b 55 ec                mov    -0x14(%rbp),%edx
4004e3:   8b 45 e8                mov    -0x18(%rbp),%eax
4004e6:   01 d0                   add    %edx,%eax
4004e8:   89 45 fc                mov    %eax,-0x4(%rbp)
4004eb:   8b 45 fc                mov    -0x4(%rbp),%eax
4004ee:   5d                      pop    %rbp
4004ef:   c3                      retq

00000000004004f0 <test2>:
4004f0:   55                      push   %rbp
4004f1:   48 89 e5                mov    %rsp,%rbp
4004f4:   48 83 ec 18             sub    $0x18,%rsp
4004f8:   89 7d ec                mov    %edi,-0x14(%rbp)
4004fb:   89 f0                   mov    %esi,%eax
4004fd:   88 45 e8                mov    %al,-0x18(%rbp)
400500:   be 28 00 00 00          mov    $0x28,%esi
400505:   bf 1e 00 00 00          mov    $0x1e,%edi
40050a:   e8 c7 ff ff ff          callq  4004d6 <test1>
40050f:   89 45 fc                mov    %eax,-0x4(%rbp)
400512:   8b 45 fc                mov    -0x4(%rbp),%eax
400515:   c9                      leaveq
400516:   c3                      retq

0000000000400517 <main>:
400517:   55                      push   %rbp
400518:   48 89 e5                mov    %rsp,%rbp
40051b:   48 83 ec 20             sub    $0x20,%rsp
40051f:   89 7d ec                mov    %edi,-0x14(%rbp)
400522:   48 89 75 e0             mov    %rsi,-0x20(%rbp)
400526:   c7 45 f0 02 00 00 00    movl   $0x2,-0x10(%rbp)
40052d:   c7 45 f4 01 00 00 00    movl   $0x1,-0xc(%rbp)
400534:   c7 45 f8 03 00 00 00    movl   $0x3,-0x8(%rbp)
40053b:   be 14 00 00 00          mov    $0x14,%esi
400540:   bf 0a 00 00 00          mov    $0xa,%edi
400545:   e8 a6 ff ff ff          callq  4004f0 <test2>
40054a:   89 45 fc                mov    %eax,-0x4(%rbp)
40054d:   8b 45 fc                mov    -0x4(%rbp),%eax
400550:   c9                      leaveq
400551:   c3                      retq
400552:   66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
400559:   00 00 00
40055c:   0f 1f 40 00             nopl   0x0(%rax)

0000000000400560 <__libc_csu_init>:
400560:   41 57                   push   %r15
400562:   41 56                   push   %r14
400564:   41 89 ff                mov    %edi,%r15d
400567:   41 55                   push   %r13
400569:   41 54                   push   %r12
40056b:   4c 8d 25 9e 08 20 00    lea    0x20089e(%rip),%r12        # 600e10 <__frame_dummy_init_array_entry>
400572:   55                      push   %rbp
400573:   48 8d 2d 9e 08 20 00    lea    0x20089e(%rip),%rbp        # 600e18 <__init_array_end>
40057a:   53                      push   %rbx
40057b:   49 89 f6                mov    %rsi,%r14
40057e:   49 89 d5                mov    %rdx,%r13
400581:   4c 29 e5                sub    %r12,%rbp
400584:   48 83 ec 08             sub    $0x8,%rsp
400588:   48 c1 fd 03             sar    $0x3,%rbp
40058c:   e8 ff fd ff ff          callq  400390 <_init>
400591:   48 85 ed                test   %rbp,%rbp
400594:   74 20                   je     4005b6 <__libc_csu_init+0x56>
400596:   31 db                   xor    %ebx,%ebx
400598:   0f 1f 84 00 00 00 00    nopl   0x0(%rax,%rax,1)
40059f:   00
4005a0:   4c 89 ea                mov    %r13,%rdx
4005a3:   4c 89 f6                mov    %r14,%rsi
4005a6:   44 89 ff                mov    %r15d,%edi
4005a9:   41 ff 14 dc             callq  *(%r12,%rbx,8)
4005ad:   48 83 c3 01             add    $0x1,%rbx
4005b1:   48 39 eb                cmp    %rbp,%rbx
4005b4:   75 ea                   jne    4005a0 <__libc_csu_init+0x40>
4005b6:   48 83 c4 08             add    $0x8,%rsp
4005ba:   5b                      pop    %rbx
4005bb:   5d                      pop    %rbp
4005bc:   41 5c                   pop    %r12
4005be:   41 5d                   pop    %r13
4005c0:   41 5e                   pop    %r14
4005c2:   41 5f                   pop    %r15
4005c4:   c3                      retq
4005c5:   90                      nop
4005c6:   66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
4005cd:   00 00 00

00000000004005d0 <__libc_csu_fini>:
4005d0:   f3 c3                   repz retq

Disassembly of section .fini:

00000000004005d4 <_fini>:
4005d4:   48 83 ec 08             sub    $0x8,%rsp
4005d8:   48 83 c4 08             add    $0x8,%rsp
4005dc:   c3                      retq

/*
在对汇编进行分析之前,我们首先简单介绍一下基本的汇编命令
*/

特殊用途的寄存器:
ax:存放函数返回值
bp:存放栈底
sp:存放栈顶
ip:存放下一条执行指令
di,si:依次对应函数的第一个参数、第二个参数.....

push  %rbp 等价于://先把sp-2,再把rbp值mov进内存
sub 0x02,%rsp
mov %rbp,(%rsp)

pop %rbp 等价于:
mov (%rsp),%rbp
add 0x02,%rsp

call指令:首先将返回地址压入栈顶,然后跳转,相当于push和jump

ret指令则是将栈顶的返回地址弹出到eip,然后按对应指令继续运行

leave 等价于:
movl %ebp %esp
pop %ebp

/*
下面我们摘取最熟悉的main函数进行分析
*/

00000000004004d6 <test1>:

/*
进入test1后,同样进行当前栈底入栈保存,但可以发现存在不同点:rsp不下偏,进行新的栈帧空间开辟。
这是因为test1函数不会继续调用子函数,所以它使用的局部变量不需要继续使用。
*/
4004d6:   55                      push   %rbp
4004d7:   48 89 e5                mov    %rsp,%rbp

//同样的,将保存在寄存器中入参值写入内存进行保存
4004da:   89 7d ec                mov    %edi,-0x14(%rbp)
4004dd:   89 75 e8                mov    %esi,-0x18(%rbp)

//进行运算
4004e0:   8b 55 ec                mov    -0x14(%rbp),%edx
4004e3:   8b 45 e8                mov    -0x18(%rbp),%eax
4004e6:   01 d0                   add    %edx,%eax
4004e8:   89 45 fc                mov    %eax,-0x4(%rbp)

//ax寄存器被用来存储函数返回值,所以把返回结果写入eax寄存器
4004eb:   8b 45 fc                mov    -0x4(%rbp),%eax

/*由于此时rsp没有下偏开辟新的栈空间,因此rsp指向内存地址的值为调用函数的栈底,
因此通过pop将栈底寄存器值恢复成被调用函数栈底地址
*/
4004ee:   5d                      pop    %rbp

//将栈顶的返回地址弹出到eip,然后按对应指令继续运行
4004ef:   c3                      retq

00000000004004f0 <test2>:

/*当函数被调用时,主要工作包括:
1.保存调用函数的栈帧情况,主要是栈底地址,因此需要将当前栈底地址push入栈。
2.保存调用函数栈底后,被调用函数即以当前栈顶为栈底,随后栈底下偏,相当于开辟一段栈空间给被调用函数使用。
*/
4004f0:   55                      push   %rbp  //同样的,进入后首先将栈底地址压栈
4004f1:   48 89 e5                mov    %rsp,%rbp
4004f4:   48 83 ec 18             sub    $0x18,%rsp

//同样的,将保存在寄存器中入参值写入内存进行保存
4004f8:   89 7d ec                mov    %edi,-0x14(%rbp)
4004fb:   89 f0                   mov    %esi,%eax
4004fd:   88 45 e8                mov    %al,-0x18(%rbp)

/*
如同main函数,test2内部也将调用一个子函数,为此将做相同的准备工作,包括:
1.将需要传递的参数从右向左依次存入对应的寄存器进行保存和传递;
2.使用callq指令,调用test1;
3.callq指令首先把返回地址push压栈,使得当函数返回时,可从该地址继续执行,随后jump至对应的内存地址(处于正文段)进行执行。
*/
400500:   be 28 00 00 00          mov    $0x28,%esi
400505:   bf 1e 00 00 00          mov    $0x1e,%edi
40050a:   e8 c7 ff ff ff          callq  4004d6 <test1>

//从test1函数返回后,将返回值写入ax寄存器保存、传递
40050f:   89 45 fc                mov    %eax,-0x4(%rbp)
400512:   8b 45 fc                mov    -0x4(%rbp),%eax

/*由于此时rsp下偏开辟新的栈空间,因此不能向test1中直接pop,需要使用leaveq命令;
leaveq命令首先将rbp值复制给rsp,再pop,同样的都是将栈底寄存器值恢复成被调用函数栈底地址
*/
400515:   c9                      leaveq

//将栈顶的返回地址弹出到eip,然后按对应指令继续运行
400516:   c3                      retq

0000000000400517 <main>:
400517:   55                      push   %rbp   //首先把当前栈底压入栈中,即将当前栈底指向的内存地址保存下来

//下面两句通过使改变rsp、rbp寄存器值来使栈顶和栈底指向不同的内存地址,相当于开辟了一段栈空间供调用函数使用,具体开辟多大,在编译时就已经计算完毕。
400518:   48 89 e5                mov    %rsp,%rbp  //把rsp所存储的栈顶地址赋值给rbp寄存器
40051b:   48 83 ec 20             sub    $0x20,%rsp //rsp存储的内存地址向下偏移0x20

//下面两句将main函数的两个入参分别写入内存,进行保存
40051f:   89 7d ec                mov    %edi,-0x14(%rbp)  //把edi寄存器值放入rbp下偏0x14的内存地址中
400522:   48 89 75 e0             mov    %rsi,-0x20(%rbp)  //把rsi寄存器值放入rbp下偏0x20的内存地址中

//将函数内部定义的局部变量依次写入内存进行保存
400526:   c7 45 f0 02 00 00 00    movl   $0x2,-0x10(%rbp)
40052d:   c7 45 f4 01 00 00 00    movl   $0x1,-0xc(%rbp)
400534:   c7 45 f8 03 00 00 00    movl   $0x3,-0x8(%rbp)

/*
可以看到main函数即将调用子函数test2,为此将做一些准备工作,包括:
1.将需要传递的参数从右向左依次存入对应的寄存器进行保存和传递;
2.使用callq指令,调用test2;
3.callq指令首先把返回地址push压栈,使得当函数返回时,可从该地址继续执行,随后jump至对应的内存地址(处于正文段)进行执行。
*/
40053b:   be 14 00 00 00          mov    $0x14,%esi
400540:   bf 0a 00 00 00          mov    $0xa,%edi
400545:   e8 a6 ff ff ff          callq  4004f0 <test2>

//从test2函数返回后,将存储在ax中的被调用函数返回值写入内存保存
40054a:   89 45 fc                mov    %eax,-0x4(%rbp)

//main函数返回值写入ax寄存器
40054d:   8b 45 fc                mov    -0x4(%rbp),%eax

//下面与test2中同理
400550:   c9                      leaveq
400551:   c3                      retq

400552:   66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
400559:   00 00 00
40055c:   0f 1f 40 00             nopl   0x0(%rax)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  函数调用 堆栈