摘自自博客网址 http://www.cnblogs.com/bangerlee/archive/2012/05/22/2508772.html

  • ax(accumulator): 可用于存放函数返回值
  • bp(base pointer): 用于存放执行中的函数对应的栈帧的栈底地址
  • sp(stack poinger): 用于存放执行中的函数对应的栈帧的栈顶地址
  • ip(instruction pointer): 指向当前执行指令的下一条指令

example code:

//func_call.c

int bar(int c, int d)

{

int e = c + d;

return e;

}

int foo(int a, int b)

{

return bar(a, b);

}

int main(void)

{

foo(2, 5);

return 0;

}

main函数汇编代码:

(gdb) disassemble /rm

Dump of assembler code for function main:

{

0x0000000000400521 :     55                push %rbp

0x0000000000400522 :     48 89 e5          mov %rsp,%rbp

foo(2, 5);

0x0000000000400525 :     be 05 00 00 00    mov $0x5,%esi

0x000000000040052a :     bf 02 00 00 00    mov $0x2,�i

0x000000000040052f :    e8 d2 ff ff ff    callq 0x400506

return 0;

0x0000000000400534 :    b8 00 00 00 00    mov $0x0,eax

}

0x0000000000400539 :     c9               leaveq

0x000000000040053a :     c3               retq

End of assembler dump.

函数调用关系

main->foo->bar

# gcc -g func_call.c -o func_call

反汇编分析

(gdb) start
start命令用于拉起被调试程序,并执行至main函数的开始位置
现进程跑在main函数中,我们disassemble命令显示当前函数的汇编信息:
(gdb) disassemble /rm
/m指示显示汇编指令的同时,显示相应的程序源码;/r指示显示十六进制的计算机指令(raw instruction)
一个函数被调用,首先默认要完成以下动作:
将调用函数的栈帧栈底地址入栈,即将bp寄存器的值压入调用栈中
建立新的栈帧,将被调函数的栈帧栈底地址放入bp寄存器中
以下两条指令即完成上面动作:
push %rbp
mov %rsp, %rbp
main并不是程序拉起后第一个被执行的函数,它被_start函数调用
传递参数
mov $0x5, %esi
mov $0x2, �i
或者:\\x86 is diffrent from x86_64
sub $0x8, %esp
mov $0x5, -0x4(%ebp) //栈底对应低地址
mov $0x2, -0x8(�p)
call指令完成控制全转移
0x000000000040052f 14>:     e8 d2 ff ff ff    callq  0x400506
执行完start命令后,现在程序停在0x400522的位置,下面我们通过gdb的si指令,让程序执行完call指令
(gdb) si 3
foo (a=0, b=4195328) at func_call.c:8
8 {
(gdb)
查看rsp、rbp寄存器的值,它们保存了程序实际用到的物理内存地址
(gdb) info registers rbp rsp
rbp 0x7fffffffe8e0 0x7fffffffe8e0
rsp 0x7fffffffe8d8 0x7fffffffe8d8
(gdb)
将main函数栈帧的栈底地址入栈,建立foo函数的栈帧:
0x0000000000400506 0>:     55             push   %rbp
0x0000000000400507 1>: 48 89 e5 mov %rsp,%rbp //rsp的值从哪里得到的?
将参数传入esi、edi寄存器,然后执行call指令
0x000000000040051a 20>:     e8 cd ff ff ff    callq  0x4004ec
10 }
0x000000000040051f 25>: c9 leaveq
0x0000000000400520 26>: c3 retq
最后一个被调用的函数结果保存在eax寄存器中,以作为结果返回
函数调用过程对应着调用栈的建立,而函数返回则是进行调用栈的销毁,
0x0000000000400504 24>:     c9    leaveq//相当于mov %rbp, %rsp/pop %rbp
0x0000000000400505 25>:     c3    retq
修改sp、bp寄存器记录栈帧的高、低地址,以此完成函数调转;
push/mov操作保存caller变量、指令信息,保证callee返回之后caller继续正常执行;
下一个函数的bp由sp传入,从kernel传入的?

调用栈变化过程:
call foo之前 ox400534是call后main的下一条指令地址

call bar后,汇编bar前,0x40051f是foo执行bar后的下一条指令

汇编bar后

执行完bar后


Function call process的更多相关文章

  1. nodejs笔记一--模块,全局process对象;

    一.os模块可提供操作系统的一些基本信息,它的一些常用方法如下: var os = require("os"); var result = os.platform(); //查看操 ...

  2. setTimeout和setImmediate以及process.nextTick的区别

    在javascript中我们了解到了setTimeout和setInterVal函数事件队列(任务队列)的相关知识,除了setTimeout和setInterval这两个方法外,Node.js还提供了 ...

  3. Nodejs随笔(三):全局对象之process

    process是全局对象,在任何地方都可以访问,而且它是EventEmitter的一个实例(关于EventEmitter后面会提到). process对象对一些标准的输入输出流进行了封装,如stdin ...

  4. Process Node.js 进程

    Process 进程 process.argv 是命令行参数数组,第一个元素是node,第二个元素是脚本文件名,从第三个元素开始每个元素是一个运行参数. process.stdout 标准输出流 co ...

  5. js的事件循环机制:同步与异步任务(setTimeout,setInterval)宏任务,微任务(Promise,process.nextTick)

    javascript是单线程,一切javascript版的"多线程"都是用单线程模拟出来的,通过事件循环(event loop)实现的异步. javascript事件循环 事件循环 ...

  6. node.js中process进程的概念和child_process子进程模块的使用

    进程,你可以把它理解成一个正在运行的程序.node.js中每个应用程序都是进程类的实例对象. node.js中有一个 process 全局对象,通过它我们可以获取,运行该程序的用户,环境变量等信息. ...

  7. Node.js进程管理之Process模块

    在前面Node.js事件运行机制也有提到,Node.js应用在单个线程运行,但是现在大部分服务器都是多处理器,为了方便使用多个进程,Node.js提供了3个模块.Process模块提供了访问正在运行的 ...

  8. 【APUE】Chapter8 Process Control

    这章的内容比较多.按照小节序号来组织笔记的结构:再结合函数的示例带代码标注出来需要注意的地方. 下面的内容只是个人看书时思考内容的总结,并不能代替看书(毕竟APUE是一本大多数人公认的UNIX圣经). ...

  9. node.js(API解读) - process (http://snoopyxdy.blog.163.com/blog/static/60117440201192841649337/)

    node.js(API解读) - process 2011-10-28 17:05:34|  分类: node |  标签:nodejs  nodejsprocess  node.jsprocess  ...

随机推荐

  1. [SHELL进阶] (转)最牛B的 Linux Shell 命令 (三)

    1. 更友好的显示当前挂载的文件系统 mount | column -t 这条命令适用于任何文件系统,column 用于把输出结果进行列表格式化操作,这里最主要的目的是让大家熟悉一下 columnt ...

  2. CREATE INDEX SELECT COUNT(*)

    CREATE INDEX windex_countrycode ON sales_rank (countrycode); CREATE INDEX windex_grab_amz_date ON sa ...

  3. buffer overflow vulnerabilitie

    Computer Systems A Programmer's Perspective Second Edition Avoiding security holes.For many years,bu ...

  4. P2661 信息传递 TODO-TARJAN算法

    http://www.cnblogs.com/zbtrs/p/5762788.html http://blog.csdn.net/loi_yzs/article/details/52795093 都是 ...

  5. 64 位win 7或windows 8下的visual studio不能连接Oracle数据库调试网站的问题

    在64 位win 7或windows 8系统下,visual studio直接F5运行网站调试,你会发现不能连接Oracle数据库,会报一个“ORA-06413: Connection not ope ...

  6. 文件管理php代码操作文件

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  7. 删除本地git版本库中受版本控制的文件

     git乱码解决方案汇总 乱码原因 搜索一番,发现git文件名.log乱码,是普遍问题,这其中有编码的原因,也有跨平台的原因.主要原因是Windows 系统中的Git对中文文件名采用不同的编码保存所致 ...

  8. 注册、启动、停止windows服务

    找到本机InstallUtil.exe命令 命令行下注册服务InstallUtil.exe D:\XXXXService.exe 启动服务 net start XXXXService 停止服务net ...

  9. Windows系统结合MinGW搭建软件开发环境

    MinGW介绍 MinGW,即Minimalist GNU For Windows,它包含了GNU工具集的运行环境.GCC编译器工具集以及其它的GNU程序开发工具(如make.gawk.grep等等) ...

  10. jQuery 遍历json数组的实现代码

    <script type="text/javascript"> "}]; $(d1).each(function(){ alert(this.text+&qu ...