资讯专栏INFORMATION COLUMN

关于C代码在linux中的汇编分析

shadowbook / 1642人阅读

摘要:即将数据压栈,指令相当于执行之后,指向下一条指令,变为执行,,之后指向下一条指令,变为执行执行等价于每进入一个函数都会执行这两个汇编指令这两步操作是个规范化步骤叫做前序。

作者 云青
原创作品转载请注明出处

基本的汇编知识:

movl,subl,pushl,topl,ret,addl,leave,enter

参考资料下载地址。http://pan.baidu.com/s/1cdISDC
课程地址:《Linux内核分析》MOOC课程http://mooc.study.163.com/cou...

一、准备

创建文件,并进行编译

int g(int x)
{
  return x + 3;
}
 
int f(int x)
{
  return g(x);
}
 
int main(void)
{
  return f(8) + 1;
}

编译命令:

gcc -S -o demo1.s demo1.c -m32

运行完毕后生成如下文件:

    .file    "demo1.c"
    .text
    .globl    g
    .type    g, @function
g:
.LFB0:
    .cfi_startproc
    pushl    %ebp
    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8
    movl    %esp, %ebp
    .cfi_def_cfa_register 5
    movl    8(%ebp), %eax
    addl    $3, %eax
    popl    %ebp
    .cfi_restore 5
    .cfi_def_cfa 4, 4
    ret
    .cfi_endproc
.LFE0:
    .size    g, .-g
    .globl    f
    .type    f, @function
f:
.LFB1:
    .cfi_startproc
    pushl    %ebp
    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8
    movl    %esp, %ebp
    .cfi_def_cfa_register 5
    subl    $4, %esp
    movl    8(%ebp), %eax
    movl    %eax, (%esp)
    call    g
    leave
    .cfi_restore 5
    .cfi_def_cfa 4, 4
    ret
    .cfi_endproc
.LFE1:
    .size    f, .-f
    .globl    main
    .type    main, @function
main:
.LFB2:
    .cfi_startproc
    pushl    %ebp
    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8
    movl    %esp, %ebp
    .cfi_def_cfa_register 5
    subl    $4, %esp
    movl    $8, (%esp)
    call    f
    addl    $1, %eax
    leave
    .cfi_restore 5
    .cfi_def_cfa 4, 4
    ret
    .cfi_endproc
.LFE2:
    .size    main, .-main
    .ident    "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4"
    .section    .note.GNU-stack,"",@progbits

我们将命令简化得到如下汇编指令:

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

备注:
%开头表示寄存器
$开头表示立即数
()表示间接寻址,样例(GAS = C语言):(%eax)= *eax [[2]](http://www.cnblogs.com/lxgeek...
Imm(Ea) ,变址寻址,样例(GAS = C语言):4(%eax) = *(4+eax)

二、汇编指令执行流程分析

我们以简化版为例:

C语言的都是从mian函数开始运行的,同理,汇编也是从main函数开始运行的,下面我们来从main函数入手。
首先执行的是18行pushl指令,
先画出内存的栈此时的情况:esp和ebp此时都指向栈底。

pushl %ebx ,即将数据压栈,指令相当于

subl $4, %esp
movl %ebx,(%esp)

执行pushl %ebp之后,eip指向下一条指令,变为:

2、执行movl %esp,%ebp,之后eip指向下一条指令,变为

3、执行 subl $4, %esp

4、执行movl $8, (%esp)

5 、call f

call f等价于

pushl %eip
movl f %eip

6 、pushl %ebp

7、movl %esp, %ebp

8、 subl $4, %esp

9、movl 8(%ebp), %eax

10、movl %eax, (%esp)

11、call g

12、

pushl %ebp

movl %esp,%ebp
每进入一个函数都会执行这两个汇编指令
这两步操作是个规范化步骤, 叫做前序(prologue) [1]。

执行函数时,汇编会生成一个堆栈调用框架:

具体如下:

//建立被调用者函数的堆栈框架
pushl %ebp
movl %esp,%ebp
//被调用者函数体
//do something

//拆除被调用者的函数的堆栈框架
movl %ebp,%esp
popl %ebp
ret

13、 movl 8(%ebp), %eax

14、addl $3,%eax

15、popl %ebp

popl %ebp 相当于

movl (%esp),%ebp
addl $4,%esb

16、ret
等价于 popl %eip

17、leave 等价于

movl %ebp,%esp

popl %ebp

18、ret

19、addl $1,%eax

20 leave

21、ret
main函数运行结束,将%eax的值返回,即12

参考文章:
[1]  X86汇编调用框架浅析与CFI简介
[2] http://www.cnblogs.com/lxgeek...

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/33216.html

相关文章

  • C语言进阶:程序预处理

    摘要:程序预处理本章节研究的是,源代码文件是如何一步步得到一个可执行程序的。如的语句被称为预处理指令,还有注释文本的删除,都在此阶段完成替换。目的是能够将所有文件中的代码组合到一起成一个完整的程序。终止程序可以正常也可以意外终止程序。 ...

    gxyz 评论0 收藏0
  • 来了解一下GCC编译器编译C可执行脚本的过程

    摘要:假定我们有一个程序名为的语言源代码文件,要生成一个可执行文件,最简单的办法就是一步即可完成这时,预编译编译连接一次完成,生成一个系统预设的名为的可执行文件。 GCC简介 Linux系统下的gcc(GNU C Compiler)是GNU推出的功能强大、性能优越的多平台编译器,是GNU的代表作品之一。gcc是可以在多种硬体平台上编译出可执行程序的超级编译器,其执行效率与一般的编译器相比...

    darkerXi 评论0 收藏0
  • 浅析缓冲区溢出

    摘要:缓冲区溢出是一种常见的攻击手段,原因在于缓冲区漏洞非常普遍,并且易于实现。缓冲区溢出漏洞占了远程网络攻击的绝大多数,成为远程攻击的主要手段。利用缓冲区溢出攻击可以导致程序运行失败系统崩溃等后果。 最近一直在学习缓冲区溢出漏洞的攻击,但是关于这一块的内容还是需要很多相关知识的基础,例如编程语言及反汇编工具使用。所以研究透彻还需要不少的时间,这里简单的做一个学习的总结,通过具体的实验案例对...

    Hegel_Gu 评论0 收藏0
  • 浅析缓冲区溢出

    摘要:缓冲区溢出是一种常见的攻击手段,原因在于缓冲区漏洞非常普遍,并且易于实现。缓冲区溢出漏洞占了远程网络攻击的绝大多数,成为远程攻击的主要手段。利用缓冲区溢出攻击可以导致程序运行失败系统崩溃等后果。 最近一直在学习缓冲区溢出漏洞的攻击,但是关于这一块的内容还是需要很多相关知识的基础,例如编程语言及反汇编工具使用。所以研究透彻还需要不少的时间,这里简单的做一个学习的总结,通过具体的实验案例对...

    fantix 评论0 收藏0
  • 基于汇编C/C++ 协程 - 切换上下文

    摘要:限制协程应用的最大技术条件是上下文切换。既然本系列讲的是基于汇编的协程,那么这篇文章我们就来讲讲使用汇编来进行上下文切换的原理。切换上下文也称为保存现场和恢复现场。协程结束后,会返回到函数中。 在前一篇文章《基于汇编的 C/C++ 协程 - 背景知识》中提到一个用于 C/C++ 的协程所需要实现的两大功能: 协程调度 上下文切换 其中调度,其实在技术实现上与其他的线程、进程调度没有...

    boredream 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<