首页 > 编程语言 >从汇编视角解析函数调用中的堆栈运作

从汇编视角解析函数调用中的堆栈运作

时间:2024-09-28 23:02:21浏览次数:7  
标签:视角 esp 函数调用 2024 eax ebp 堆栈 pushl

引言
汇编语言是计算机硬件操作的最直接表达方式,通过汇编代码可以深入理解计算机底层的工作机制。本文将以一个简单的C语言代码为例,深入分析其对应的汇编代码中的堆栈变化,探讨计算机在执行过程中如何通过堆栈来进行函数调用、参数传递和结果返回。

  1. C语言代码与汇编代码概述
    我们从如下简单的C语言代码开始:
int g(int x) {
    return x + 2024;
}

int f(int x) {
    return g(x);
}

int main(void) {
    return f(2024) + 1;
}

上述代码通过函数g、f、main进行一系列调用。其汇编代码如下:

g:
.LFB0:
    pushl   %ebp
    movl    %esp, %ebp
    call    __x86.get_pc_thunk.ax
    addl    $_GLOBAL_OFFSET_TABLE_, %eax
    movl    8(%ebp), %eax
    addl    $2024, %eax
    popl    %ebp
    ret

f:
.LFB1:
    pushl   %ebp
    movl    %esp, %ebp
    call    __x86.get_pc_thunk.ax
    addl    $_GLOBAL_OFFSET_TABLE_, %eax
    pushl   8(%ebp)
    call    g
    addl    $4, %esp
    leave
    ret

main:
.LFB2:
    pushl   %ebp
    movl    %esp, %ebp
    call    __x86.get_pc_thunk.ax
    addl    $_GLOBAL_OFFSET_TABLE_, %eax
    pushl   $2024
    call    f
    addl    $4, %esp
    addl    $1, %eax
    leave
    ret

__x86.get_pc_thunk.ax:
.LFB3:
    movl    (%esp), %eax
    ret  
  1. 堆栈在函数调用中的变化分析
    2.1 函数 main 的堆栈变化
    main 函数是程序的入口点。汇编代码如下:
main:
.LFB2:
    pushl   %ebp
    movl    %esp, %ebp
    call    __x86.get_pc_thunk.ax
    addl    $_GLOBAL_OFFSET_TABLE_, %eax
    pushl   $2024
    call    f
    addl    $4, %esp
    addl    $1, %eax
    leave
    ret

pushl %ebp:将当前ebp压入堆栈,保存上一层的基址指针,以便稍后恢复。
堆栈内容:[旧ebp]
movl %esp, %ebp:将当前的栈顶指针esp赋值给ebp,建立新的栈帧。
堆栈内容:[旧ebp],此时ebp和esp指向同一位置。
pushl $2024:将常数2024压入堆栈,作为传递给f函数的参数。
堆栈内容:[旧ebp] [2024]
call f:调用f函数,程序跳转至f函数的入口地址。此时返回地址被压入堆栈,以便在f函数执行完后能够返回到main函数的下一条指令。
堆栈内容:[旧ebp] [2024] [返回地址]
2.2 函数 f 的堆栈变化
函数f的汇编代码如下:

f:
.LFB1:
    pushl   %ebp
    movl    %esp, %ebp
    call    __x86.get_pc_thunk.ax
    addl    $_GLOBAL_OFFSET_TABLE_, %eax
    pushl   8(%ebp)
    call    g
    addl    $4, %esp
    leave
    ret

pushl %ebp:保存上一层的基址指针。
堆栈内容:[旧ebp] [2024] [返回地址] [旧ebp]
movl %esp, %ebp:建立新的栈帧。
堆栈内容:[旧ebp] [2024] [返回地址] [旧ebp],ebp和esp指向最后一个旧ebp。
pushl 8(%ebp):将main函数中传递给f的参数(即2024)压入堆栈,作为传递给g函数的参数。
堆栈内容:[旧ebp] [2024] [返回地址] [旧ebp] [2024]
call g:调用g函数,返回地址被压入堆栈。
堆栈内容:[旧ebp] [2024] [返回地址] [旧ebp] [2024] [返回地址]

2.3 函数 g 的堆栈变化
函数g的汇编代码如下:

g:
.LFB0:
    pushl   %ebp
    movl    %esp, %ebp
    call    __x86.get_pc_thunk.ax
    addl    $_GLOBAL_OFFSET_TABLE_, %eax
    movl    8(%ebp), %eax
    addl    $2024, %eax
    popl    %ebp
    ret

pushl %ebp:保存上一层的基址指针。
堆栈内容:[旧ebp] [2024] [返回地址] [旧ebp] [2024] [返回地址] [旧ebp]
movl %esp, %ebp:建立新的栈帧。
堆栈内容:[旧ebp] [2024] [返回地址] [旧ebp] [2024] [返回地址] [旧ebp]
movl 8(%ebp), %eax:从栈中取出2024并放入eax寄存器。
addl $2024, %eax:将2024加到eax寄存器中,结果为2024 + 2024 = 4048。
popl %ebp:恢复上一层的基址指针。
ret:从栈中弹出返回地址,并跳转回到f函数中继续执行。

3.总结:计算机是如何工作的
通过对汇编代码的深入分析,我们可以看到,堆栈在函数调用过程中起到了关键的作用。每当发生函数调用时,堆栈会保存当前函数的执行状态(如基址指针ebp和返回地址),并为被调用函数分配空间。函数调用结束后,通过恢复堆栈中的数据,程序能够准确地回到上一次的执行状态。

堆栈不仅用于函数调用和返回,它还用于参数传递和局部变量的存储。计算机的工作可以被理解为:通过指令和堆栈的相互作用来管理程序的执行流程,确保不同函数之间的信息能够无缝地传递和恢复。

总结来说,计算机的工作原理是通过CPU执行一条条指令,同时通过寄存器和堆栈维护程序的状态。堆栈在这一过程中扮演了“信息中转站”的角色,确保程序能够正确且有序地执行各个函数及其关联操作。

标签:视角,esp,函数调用,2024,eax,ebp,堆栈,pushl
From: https://www.cnblogs.com/test0ne/p/18438515

相关文章

  • 执行上下文和调用堆栈
    为顶级代码创建全局执行上下文,即不在任何fn内的代码。因此,首先执行fn之外的代码。fn-decln/exprsn的fn主体内的代码仅在调用时执行。执行上下文(ec)一段js执行的环境。存储一些要执行的代码的所有必要信息,例如局部变量、传递给fn的args。js代码始终在ec内运行......
  • 开源!Pod高负载自动打印JAVA线程堆栈
    开源!Pod高负载自动打印JAVA线程堆栈运维技术探讨  2024年08月29日17:39 广东 以下文章来源于SRE运维手记 ,作者亦零一SRE运维手记.一个在房地产、家居科技、游戏和电商行业摸爬滚打的运维老司机#sre#k8s#kubernetes#prometheus#devops01背景     在......
  • 堆栈使用
    栈stack存在内存高地址部分类似压子弹先进后出,后进先出printf("Elementattopofthestack:%d\n",peek());printf("Elements:\n");//printstackdatawhile(!isempty()){intdata=pop();printf("%d\n",data);}printf("Stackfull:%s......
  • 数据飞轮:全新视角下的数据中台实现
    在当今数据密集的商业环境中,有效地管理和利用数据成为了企业竞争力的关键。随着「数据飞轮(DataFlywheel)」理念的提出,与传统的数据中台(DataMiddlePlatform)相比,我们可能会探讨它们是否是同一事物的不同阶段,或者它们是否具备本质的差异。从私域运营到全链路营销,数据如何驱动策......
  • 数据飞轮视角下的金融行业数据中台构建
    在面对数据驱动时代的挑战与机遇时,金融行业的数据技术发展特别值得关注。尤其是数据飞轮与数据中台之间的关系,进一步推动了金融服务的革新。本文将探讨数据飞轮是否为数据中台的高阶形态,通过金融业务场景的具体实例,揭示二者的本质区别和互补性。数据中台和数据飞轮:基础理解数据中......
  • 数据飞轮:从数据仓库到数据中台的技术革新视角
    在当前的商业环境中,数据不只是支持决策的工具,它已经变成驱动业务增长的核心资产。从数据仓库的集中式存储、管理到数据中台的统筹调度再到数据飞轮的自我增强,每一个步骤不仅仅是技术的跃进,更是企业战略的演变。自动化营销:数据驱动的新途径在自动化营销场景中,企业通过分析用户行为......
  • Arthas thread(查看当前JVM的线程堆栈信息)
    文章目录二、命令列表2.1jvm相关命令2.1.2thread(查看当前JVM的线程堆栈信息)举例1:展示[数字]线程的运行堆栈,命令:thread线程ID举例2:找出当前阻塞其他线程的线程二、命令列表2.1jvm相关命令2.1.2thread(查看当前JVM的线程堆栈信息)使用场景:在Arthas中,thread命令用于查看和分......
  • 【Unity】CinemachineVirtualCamera:实现第一人称视角控制
    相机视角的控制,利用CinemachineVirtualCamera插件(在packageManager中下载)实现键盘和鼠标控制第一人称视角。WASD前进后退向左向右,QE左右旋转;鼠标滚轮控制远近、俯仰和升降。另外还支持鼠标靠近边缘移动、鼠标拖拽等控制方式。成果展示Scene部分主相机增加CinemachineBrain组......
  • 教师师德师风研判:多维视角下的全面审视
    在教育这片神圣的土地上,教师不仅是知识的传播者,更是学生品德形成的引路人。师德师风,作为教师队伍建设的灵魂,直接关系到教育的质量和方向。本文将从政治素质和思想品德、职业道德和行为规范、教育教学能力、学术诚信和科研行为、社会责任感和服务意识、自我修养和终身学习、学生......
  • 业财一体化视角下-电商ERP采购模块的设计
    本文将深入探讨如何在采购模块的设计中有效体现业财一体化理念,从财务三大报表的基本概念出发,详细解析采购过程中的财务管理关键要素,并分享采购流程设计中应注意的重点,以期为企业提供有价值的参考和指导。业财一体化的重要性日益凸显,越来越多企业认识到业务运营与财务管理的......