Linux下的C语言的执行流程与汇编分析

本文深入探讨Linux环境下C语言的执行流程,从汇编基础开始,包括主要汇编指令、寻址方式和堆栈原理。通过分析简单的C程序编译成的汇编代码,揭示函数调用、堆栈操作以及CPU执行过程,揭示了计算机如何理解和执行高级语言程序。
摘要由CSDN通过智能技术生成

作者:鲍迪
原创作品转载请注明出处
《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000


1. 汇编基础

本汇编基础均建立在Linux系统下,也就是采用AT&T汇编格式

1.1一些主要的汇编指令


汇编指令功能等价指令
mov传送字或字节-
add加法-
sub减法-
pushl %eax压栈subl $4,%esp
movl %eax,(%esp)
popl %eax出栈movl (%esp),%eax
addl $4,%esp
call 0x12345过程调用pushl %eip
movl $0x12345,%eip
enter重设堆栈pushl %ebp
movl %esp,%ebp
leave撤销堆栈movl %ebp,%esp
popl %ebp
ret过程返回popl %eip
注:命令后面的b、w、l、q分别代表着8位、16位、32位和64位,例如:movl即代表传送一个32位的数据。


1.2 几种主要的寻址方式


寻址方式示例操作结果
寄存器寻址(register mode)movl %eax,%edxedx = eax
立即数寻址(immediate)movl $0x123edx = 0x123
直接寻址(direct)movl 0x123,%edxedx = * (int32_t*)0x123
间接寻址(indrect)movl (%ebx),%edxedx = * (int32_t*)ebx
变址寻址(displaced)movl 4(%ebx),%edxedx = * (int32_t*)(ebx+40)


1.3 堆栈介绍


说到汇编还有个不得不提的就是堆栈(即栈),下图是大多数体系结构虚拟地址空间的分配情况:


虚拟地址空间
( 图片来自网络)


而堆栈是虚拟地址空间里面比较特殊的一段,除了栈是从高地址往低地址方向增长,其他部分均是由低往高增长,而pop和push指令正是借助这一特性进行压栈和出栈。它的操作方式是只在栈顶进行压栈和出栈操作,如下图所示:

栈的操作示意图
( 图片来自网络)



2. C语言的执行流程与汇编分析


学过C语言的都知道,C程序要被CPU执行,还要被编译为汇编程序,再由汇编程序翻译成为能被CPU识别的可执行程序。接下来我们利用下面一段简单的C程序来编译成汇编代码以分析其工作过程及堆栈变化。

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

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

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

经过
gcc –S –o main.s main.c -m32 命令
编译之后得到汇编代码,如图:


汇编1


删除了代码里面的辅助信息之后得到纯汇编代码,如下图:


汇编2

即:

g:
    pushl   %ebp
    movl    %esp, %ebp
    movl    8(%ebp), %eax
    addl    $4, %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    $4, (%esp)
    call    f
    addl    $4, %eax
    leave
    ret

从上面的汇编代码可以看出,不论是main函数还是f,g函数,函数头部的语句必为

pushl   %ebp
movl    %esp, %ebp

即指令enter,在本函数功能执行之前重设一个新的堆栈给本函数使用,保存前一个函数的栈基址,而同时注意到main和f函数后部都有leave,而g函数因为esp寄存器没有变化了,所以被编译器优化了只剩

popl    %ebp

进行退栈操作。

除此之外,main函数剩余指令的操作为

subl    $4, %esp   将栈顶指针esp的值减4
movl    $4, (%esp) 指将参数4压入栈
call    f          先把eip压入栈,在跳转到f处去执行
addl    $4, %eax   指函数返回值存在寄存器eax中,并对其值加4

跳转到f函数时剩余语句的操作为

subl    $4, %esp       将f函数栈顶地址减4
movl    8(%ebp), %eax  间接寻址,将ebp寄存器加8的位置里面存放的内容移                            
                       到eax寄存器中
movl    %eax, (%esp)   将eax值写入堆栈
call    g              先把eip压入栈,在跳转到g处去执行

跳转到g函数时剩余语句的操作为

movl    8(%ebp), %eax 间接寻址,将ebp寄存器加8的位置里面存放的内容移到
                      eax寄存器中
addl    $4, %eax      寄存器eax加4

汇编程序执行期间,堆栈的操作示意图如下
这里写图片描述

最后由ret指令执行各个函数的返回操作。


3. 总结


经过对由C语言编译成的汇编代码执行过程分析,可以看出,计算机的工作原理为由编译器链接器等工具将高级语言转换成计算机能理解的可执行程序,借助堆栈机制在保证程序的执行,然后由CPU按照eip寄存器的指向一步一步执行程序,从而形成计算机的执行流程。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值