关于函数调用浅析

栈在程序运行中有重要的地位,栈保存了一个函数调用所需要的维护信息,这通常被称为栈帧活动记录

在i386中,一个函数的活动记录用ebpesp这两个寄存器划定活动范围:

  • esp寄存器始终指向栈的顶部,也就指向了当前函数的活动记录的顶部。
  • ebp指向了活动记录的栈的底部,ebp又被称为帧指针
活动记录.png

随着函数的执行,esp会不断的变化;固定不变的ebp可以用来定位函数活动记录的各个数据。
栈帧一般包括如下内容:

  • 函数的参数和返回地址。
  • 临时变量,包括函数的局部变量和编译器自动生成的临时变量
  • 保存的上下文,函数调用前后需要保持不变的寄存器

C 语言调用约定:
在C语言中,函数参数是从右到左的顺序入栈的,同时参数是在栈中传递的, EAX,ECX 和 EDX 寄存器是由调用者保存的,其余的寄存器由被调用者保存,函数的返回值存储在 EAX 寄存器中。由调用者清理栈空间。

那么下面一段函数调用是怎么完成的呢?

int subtract(int a, int b)
{
    return a - b;
}

int main()
{
    int a = 10;
    int b = 20;
    int sub = subtract(a, b);
    printf("sub: %d\n", a - b);
}

结合函数调用约定那么汇编代码大概如下:

int subtract(int a, int b)
{
 64a:   55                      push   %rbp
 64b:   48 89 e5                mov    %rsp,%rbp
 64e:   89 7d fc                mov    %edi,-0x4(%rbp)
 651:   89 75 f8                mov    %esi,-0x8(%rbp)
    return a - b;
 654:   8b 45 fc                mov    -0x4(%rbp),%eax
 657:   2b 45 f8                sub    -0x8(%rbp),%eax
}
 65a:   5d                      pop    %rbp
 65b:   c3                      retq   

000000000000065c <main>:

int main()
{
 65c:   55                      push   %rbp
 65d:   48 89 e5                mov    %rsp,%rbp
 660:   48 83 ec 10             sub    $0x10,%rsp
    int a = 10;
 664:   c7 45 f4 0a 00 00 00    movl   $0xa,-0xc(%rbp)
    int b = 20;
 66b:   c7 45 f8 14 00 00 00    movl   $0x14,-0x8(%rbp)
    int sub = subtract(a, b);
 672:   8b 55 f8                mov    -0x8(%rbp),%edx
 675:   8b 45 f4                mov    -0xc(%rbp),%eax
 678:   89 d6                   mov    %edx,%esi
 67a:   89 c7                   mov    %eax,%edi
 67c:   e8 c9 ff ff ff          callq  64a <_Z8subtractii>
 681:   89 45 fc                mov    %eax,-0x4(%rbp)
    printf("sub: %d\n", sub);
 684:   8b 45 fc                mov    -0x4(%rbp),%eax
 687:   89 c6                   mov    %eax,%esi
 689:   48 8d 3d a4 00 00 00    lea    0xa4(%rip),%rdi        # 734 <_IO_stdin_used+0x4>
 690:   b8 00 00 00 00          mov    $0x0,%eax
 695:   e8 86 fe ff ff          callq  520 <printf@plt>

}
  • push %rbp
    mov %rsp, %rbp

    image.png
  • sub $0x10,%rsp
    movl $0xa,-0xc(%rbp)
    movl $0x14,-0x8(%rbp)

    image.png
  • mov -0x8(%rbp), %edx
    mov -0xc(%rbp), %eax
    mov %edx, %esi
    mov %eax, %edi

    准备参数。

  • callq 64a <_Z8subtractii>
    CPU执行call指令时,进行2步操作:
    1、将当前的IP或CS和IP压入栈中
    2、转移,这里跳转到subtract函数的机器指令

    image.png
  • push %rbp
    mov %rsp, %rbp

    image.png
  • mov %edi, -0x4(%rbp)
    mov %esi, -0x8(%rbp)
    准备参数,参与计算
image.png
  • mov -0x4(%rbp),%eax
    sub -0x8(%rbp),%eax

    将 eax 寄存器的值和 -0x8(%rbp) 地址的值相减,将结果赋值给 eax

  • pop %rbp
    恢复到main函数栈帧

    image.png

  • retq
    CPU执行ret指令时,进行2步操作:
    1、将当前的栈中的值赋值给IP寄存器,这里回到了main函数执行流。
    2、出栈

    image.png
  • mov %eax, -0x4(%rbp)
    将 eax 的值赋值给 -0x4(%rbp)

    image.png
x64通用寄存器用途
image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,723评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,485评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,998评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,323评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,355评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,079评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,389评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,019评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,519评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,971评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,100评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,738评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,293评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,289评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,517评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,547评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,834评论 2 345

推荐阅读更多精彩内容

  • 栈: 在函数调用时,第一个进栈的是主函数中函数调用后的下一条指令(函数调用语句的下一条可执行语句)的地址,然后是函...
    zjfclimin阅读 3,922评论 0 5
  • 阅读经典——《深入理解计算机系统》04 函数调用时的栈结构变化是一个很有趣的话题,本文就来详细剖析这个过程。 栈帧...
    金戈大王阅读 23,180评论 14 36
  • 原文地址:C语言函数调用栈(一)C语言函数调用栈(二) 0 引言 程序的执行过程可看作连续的函数调用。当一个函数执...
    小猪啊呜阅读 4,590评论 1 19
  • 堆栈是什么: 堆栈是内存的一种先进后出的存储方式,具有由高地址向低地址生长的特质。(像是以空气为地基,往地底建房...
    manchanson阅读 762评论 0 0
  • 推荐指数: 6.0 书籍主旨关键词:特权、焦点、注意力、语言联想、情景联想 观点: 1.统计学现在叫数据分析,社会...
    Jenaral阅读 5,701评论 0 5