zoukankan      html  css  js  c++  java
  • 计算机专业课系列之二:程序的机器表示(汇编)

     一,预备知识:

    1,堆栈

    应用:函数调用(先进后出),数组遍历,表达式计算

    2,寄存器

    寄存器是是cpu中临时存储数据的地方,非常小,但是非常快。cpu进行计算时,cpu不能直接对内存中的两个数据进行操作。他必须先装入寄存器中,然后才进行加减等操作。

    我们最常用的是AX,BX,CX,DX。它们都是16位的。现在都扩展到了32位。低位(0-15)有时候运算用不了这么多,所以低位可以拆分为   高位AH(8-15),低位AL(0-7)。

    A,B,C,D都是通用的寄存器,在进行数据处理时,可以用。

    ESI(source),EDI(destination)在拷贝数据时用到,

    ESP:永远指向栈的栈顶

    EBP:描述了一个栈帧,EBP永远指向一个栈帧的开始处

    3, 汇编

    4,指针

    指针就是内存地址。

     

    二,例子:

    C语言代码

    再看程序的机器表示(汇编):

     进程的虚拟地址空间

     

     函数帧:

    每个函数都有栈帧,里面存放上一个栈帧的地址,输入参数,返回值等

     地址由大到小,如果满了,就会出现堆栈溢出。

    寄存器的理解

    EBP:是一个寄存器,里面存一个值,这个值是指向内存中的当前函数栈帧的开始处(指向函数帧2的开始处,函数帧2是当前栈帧)。

    但是函数帧1的的开始处怎么存呢?因为只有一个ebp,所有的函数帧开始地址都要存放在ebp中。那么可以把所有的函数帧开始地址压到栈中

    ESP:是一个指向栈顶的寄存器,每次做push操作,esp会自动减(栈向下生长)。调用pop操作,esp自动加(栈收缩)。注意:栈是从上往下生长的。栈地址是从大往小生长的,栈底是在最上面的。

    理解:

    每个函数调用都会生成栈帧。是动态生成的。函数中的变量,比如:Int a =10;可以在编译时就分配好内存。所以是静态的。

    malloc是堆,运行时才分配出内存。所以是动态的。

    第一步:

    说明:%ebp中的%表示对ebp的引用 

    pushl %ebp :把ebp中的值(1000)放到栈顶(内存中),此时esp自动减4(804减到800)。

    movl %esp %ebp:把esp中的值放到ebp中(ebp由1000变为800),所以现在esp的值等于ebp的值

    第二步:

    subl %24esp:把栈顶esp的值减24,如图:

    为什么要减去24呢?

    这跟编译器有关,其实是用来给函数帧分配内存空间,原来是地址是800,减去24,等于776。从ebp指向的位置(栈帧的开始处)到当前esp指向的位置,这中间其实有32个字节。都是为这个函数使用的。因为X86的编程指导方针,是为了严格的数据对齐导致的。一个函数使用的栈空间,必须是16个字节的整数倍。保存上一个函数栈帧的开始处用了4个字节,返回值也用了4个字节,再加上刚刚分配的24个字节,整好是32个字节。此时,ebp:地址是800,指向了新的函数栈帧。

    第三步:

    movl $10 -4(%ebp):把10放到寄存器ebp内存地址减4的位置

    movl $20 -8(%ebp):把10放到寄存器ebp内存地址减8的位置

     这样就把10,20放入内存中了(比如我们定义了int a=10,int b=20)。注意:ebp的地址并没有变。

    问题:那么 指向10,20 的变量名在哪?

    答案:根本就不存在,机器级根本就没有变量名,因为这里都是对地址进行操作。编译时完全把变量名去掉了。

    第四步:

    leal -8(%ebp) %eax:leal表示取地址,取到的地址为792(800-8),然后放到eax中。

    movl %eax 4(%esp):把eax的值(792)放到esp加4处(780)。这是变量y的地址放到这里。接下来调用函数,函数需要用到这个地址

    leal -4(%ebp) %eax:同上,把变量x的地址放到这里。存变量地址

    movl %eax (%esp):把变量的地址给esp

    至此,函数的参数准备已经完成了。

    第五步:函数调用

    函数调用后,把返回地址放到内存中。

     第六步:add函数

    这几步没听懂,头大。

  • 相关阅读:
    ISO/IEC 9899:2011 条款6.10.3——宏替换
    ISO/IEC 9899:2011 条款6.10.2——源文件包含
    关于Objective-C新增的__kindof关键字
    ISO/IEC 9899:2011 条款6.10.1——条件包含
    ISO/IEC 9899:2011 条款6.10——预处理指示符
    ISO/IEC 9899:2011 条款6.9.2——外部对象定义
    Objective-C中使用不定参数个数的方法调用
    php添加数据到xml文件的例子
    nginx rewrite重写与防盗链配置
    nginx url自动加斜杠的问题
  • 原文地址:https://www.cnblogs.com/inspred/p/10747777.html
Copyright © 2011-2022 走看看