c语言函数变化过程,C语言函数调用过程(汇编分析)

本文深入探讨了C语言函数调用的汇编层面,详细解析了函数参数传递、栈帧开辟和回退的过程。通过分析源代码的反汇编,展示了CPU如何在遇到函数调用时保存现场并跳转执行,以及执行完毕后如何恢复栈帧和继续执行后续代码。了解这些细节有助于深化对C语言底层执行机制的理解。
摘要由CSDN通过智能技术生成

C语言函数调用过程(汇编分析)

C语言函数调用过程(汇编分析)

C语言函数调用过程(汇编分析)

函数调用主要的三个方面是函数名、参数列表和返回值,想要深入了解函数的调用机制,就需要深入底层,分析源文件的汇编码来分析函数调用的流程

函数调用的步骤如下:

函数参数传入

函数栈帧开辟

函数返回值

函数栈帧回退

所谓栈帧,就剩为一个函数调用单独分配的栈空间

c6dfcd7c6b20fabc11b007123b00a78b.png

图片来源:简书金戈大王

函数参数的传入和函数的返回值很好理解,它们函数输入和输出,但是函数栈帧的开辟和回退的具体作用又是怎样的呢?

函数的本意是可以重复使用的代码块,在CPU执行程序时,是逐行执行的;如果遇到函数调用,CPU会记录下当前代码块中的地址,然后跳转到函数中,当函数体执行完毕周,CPU会再次返回到当初记录的位置,继续执行后续代码

Ubuntu下查看源文件的反汇编码的查看方式如下所示:

终端输入:gcc -S filename.c

之后只需使用cat命令即可查看反汇编码

例:源程序内容如下:

#include

void fun(int a)

{

a += 1;

printf("Hello World!\n");

}

int main()

{

int val = 1;

fun(val);

return 0;

}

该程序的汇编码如下所示:(本人汇编小白,如有错误,还请大家指正)

.file"func.c"

.text

.section.rodata

.LC0:

.string"Hello World!"

.text

.globlfun

.typefun, @function

fun:

.LFB0:

.cfi_startproc

pushq%rbp

.cfi_def_cfa_offset 16

.cfi_offset 6, -16

movq%rsp, %rbp

.cfi_def_cfa_register 6

subq$16, %rsp

movl%edi, -4(%rbp)

addl$1, -4(%rbp)

leaq.LC0(%rip), %rdi

call[email protected]

nop

leave

.cfi_def_cfa 7, 8

ret

.cfi_endproc

.LFE0:

.sizefun, .-fun

.globlmain

.typemain, @function

main:

.LFB1:

.cfi_startproc

pushq%rbp

.cfi_def_cfa_offset 16

.cfi_offset 6, -16

movq%rsp, %rbp

.cfi_def_cfa_register 6

subq$16, %rsp

movl$1, -4(%rbp)

movl-4(%rbp), %eax

movl%eax, %edi

callfun

movl$0, %eax

leave

.cfi_def_cfa 7, 8

ret

.cfi_endproc

.LFE1:

.sizemain, .-main

.ident"GCC: (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0"

.section.note.GNU-stack,"",@progbits

代码中以 . 开头的代码行属于链接时使用的辅助信息,在实际中不会执行,因此可以将其删除提高代码阅读性

fun:

pushq%rbp

movq%rsp, %rbp

subq$16, %rsp

movl%edi, -4(%rbp)

addl$1, -4(%rbp)

call[email protected]

nop

leave

ret

main:

pushq%rbp

movq%rsp, %rbp

subq$16, %rsp

movl$1, -4(%rbp)

movl-4(%rbp), %eax

movl%eax, %edi

callfun

movl$0, %eax

leave

ret

汇编代码分析:

函数的通用格式如下所示:

函数名:

pushq%rbp

movq%rsp, %rbp

函数体(具体代码)

leave

ret

首先需要明确的是,rsp为栈顶寄存器,rbp为栈底寄存器,push为在栈顶寄存器存放数据,栈顶上移

leave相当于

movl%ebp, %esp

pop1%ebp

其作用为恢复堆栈指针,具体步骤如下:使用movl将当前栈指针指向当前帧的起始位置,之后再恢复帧指针,这样,popl调用之后,程序将完全退出当前帧

根据以上汇编码可以分析函数执行过程如下:

每次call一个函数,函数总是先把当前的栈底指针压入堆栈,然后把栈底指针移动到当前栈顶,这样就相当于在旧栈上新开辟一个栈,等被调用的函数执行的时候,CPU依次执行栈中的指令,然后再依次出栈,也就是说,当函数执行完毕,再恢复堆栈指针之后,栈顶指针又回到了函数调用的位置

C语言函数调用过程(汇编分析)相关教程

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值