zoukankan      html  css  js  c++  java
  • 汇编学习-堆栈与子程序

    不论什么程序在执行过程中都须要使用堆栈,操作系统为每个程序(进程及线程)设置一个堆栈。

    在使用高级语言编程时。源程序中使用的函数调用、局部变量都要用到堆栈。由编译器来负责生成有关的机器指令。我的理解,堆栈就是维护当前线程中执行状态的一个数据结构,这样的状态包含:须要传递的变量,函数的返回地址,局部变量等等。

    与堆栈相关的 3 个寄存器是:SS, ESP, EBP。
    ESP 寄存器中的内容作为堆栈的当前指针。PUSH, POP, CALL, RET 等指令都与堆栈有关,使用 SS:ESP 指向堆栈单元。


    EBP 寄存器中的内容作为堆栈的“基准”指针。SS:EBP 指向的地址作为基准地址。在函数(子程序)内部。能够使用 [EBP+马上数] 的形式来取得主程序传递的參数,使用 [EBP-马上数] 的形式来訪问局部变量。


    从上述的描写叙述能够看出。整个堆栈的是一个经典的先入后出的栈结构。在栈中还存在着“栈帧”这种结构,用来表示当前函数执行的环境,里面存放着当前函数的局部变量,所需的返回地址。栈帧由 EBP 所指出。EBP 和 ESP 之间即为当前函数帧,调用函数和被调用函数的栈帧是相邻存放,这样就可以通过 EBP加减固定的数,来获取主调函数所传递的函数參数。
    上述的堆栈结构例如以下:


    堆栈是经过精心设计的结构,使得编程人员能够方便的设计函数来实现结构化设计,高级语言也得益于这样的结构。c 语言基本上就是汇编的一种简单的翻译。这里要强调的是,在用汇编敲代码的时候,全然能够不按这样的结构来设计。比方參数我们能够放到指定的内存区,被调用的函数到指定的内存区去取出传递给它的參数。也能够让函数參数所有通过寄存器来传送,尤其是在 ARM 这样的寄存器特别多,并且每一个寄存器的地位都同样的处理器之中。之所以要设计出堆栈,就是为了能够以统一的方式来编敲代码。

    对于 c 语言。函数有好几种调用规则。最常见的是两种。cdecl 方式和 stdcall 方式。

    Cdecl 方式
    (1)使用堆栈传递參数
    (2)主程序按从右向左的顺序将參数逐个压栈。最后一个參数先入栈。

    每个參数压栈一次。


    (3)在子程序中,使用 [EBP+X] 的方式来訪问參数。

    X=8 代表第 1 个參数;X=12 代表第二个參数。依次类推
    (4)子程序用 RET 指令返回。
    (5)由主程序运行“ADD ESP, n”指令调整 ESP。达到堆栈平衡。


    (6)一般返回值放在 EAX 中

    Stdcall 方式
    与Cdecl的不同是。堆栈的平衡不是由主程序完毕,而是由子程序通过调用“RET n”指令主动平衡。

    这些调用规则,都是针对 c 语言来说的,在 c 语言和汇编须要互相调用的情况;c 语言编写的不通的二进制函数库之间。都要注意函数的调用规则。

    以下举一个普通的样例

    AddProc1    proc   ; cdecl方式
        push    ebp    ; 记下上一个栈帧地址
        mov     ebp, esp
        mov     eax, dword ptr [ptr+8]  ; 取第一个參数 
        add     eax, dword ptr [ptr+12] ; 取第二个參数
        pop     ebp    ; 恢复栈帧为调用者,但这时候堆栈还未平衡
        ret
    AddProc1    endp
    AddProc2    proc   ; stdcall
        push    ebp
        mov     ebp, esp
        mov     eax, dword ptr [ptr+8]
        add     eax, dword ptr [ptr+12]
        pop     ebp
        ret     8    ; 和前面一样,唯一不同是,直接由子程序恢复堆栈。8 正好是两个參数的长度
    AddProc2    endp
    start:
        push    20
        push    10
        call    AddProc1
        add     esp, 8   ; 由主调函数恢复堆栈
        push    50
        push    60
        call    AddProc2
        ret
    end start 


       

  • 相关阅读:
    《PHP
    2018/06/11 数据库设计规范
    RequireJs 与 SeaJs的相同之处与区别
    null 与 undefinded
    page 分页
    fullPage的使用
    touch事件(寻找触摸点 e.changedTouches)
    t添加最佳视口
    随鼠标动的炫彩小球
    随机小球
  • 原文地址:https://www.cnblogs.com/mfmdaoyou/p/6905978.html
Copyright © 2011-2022 走看看