Linux内核分析(一)之简单的C语言调用栈分析

本文通过分析《Linux内核分析》课程中的实例,详细讲解了一个简单C语言程序的函数调用栈,涉及汇编代码、栈操作及寄存器变化,揭示了函数调用和返回过程中的内存管理和控制流程。
摘要由CSDN通过智能技术生成

前言

本文的内容来自于《Linux内核分析》MOOC课程。文中以一段简单的C语言代码为例解释了C语言函数调用栈的结构。

实验环境

操作系统Ubuntu 14.04 LTS,gcc版本4.8.4

程序代码

本小节中的代码如下所示:

int g(int x) {  
    return x + 1;  
}  

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

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

生成汇编代码

利用gcc编译main.c生成main.s汇编文件

$ gcc -S -o main.s main.c -m32

生成后的汇编文件中有很多以.开头的symbol,这些symbol都是与链接相关的,不在本文讨论的范围内。在把汇编文件中的链接符号删除后,得到程序执行过程中最核心的汇编代码。

g:
    pushl   %ebp
    movl    %esp, %ebp
    movl    8(%ebp), %eax
    addl    $1, %eax
    popl    %ebp
    ret
f:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $4, %esp
    movl    8(%ebp), %eax
    movl    %eax, (%esp)
    call    g
    leave
    ret
main:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $4, %esp
    movl    $1, (%esp)
    call    f
    addl    $1, %eax
    leave
    ret

汇编代码分析

接下来将对汇编代码的工作过程中堆栈和重要寄存器值的变化做详细的分析。
注意:在x86架构中,栈是负增长的。为了方便讨论,笔者在这里将栈的大小设为0x100个字节。同时,假设代码段的起始地址为0,每一个指令对应的地址为其在上文中汇编代码的行数。

程序的入口是main函数,从第18行开始。

step1

18 pushl %ebp

语义

将调用main的进程的ebp压栈

函数调用栈

地址 内容 栈指针
0x100 调用main函数进程的ebp esp
0x0FC

相关寄存器的值

寄存器
eax 未知
eip 19

step2

19 movl %esp, %ebp

语义

将esp的值赋给ebp

函数调用栈

地址 内容 栈指针
0x100 调用main函数进程的ebp esp ebp
0x0FC

相关寄存器的值

寄存器
eax 未知
eip 20

step3

20 subl $4, %esp

语义

将esp内的值减4,即栈顶指针增加一个单元

函数调用栈

地址 内容 栈指针
0x100 调用main函数进程的ebp ebp
0x0FC esp
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值