汇编语言学习 下

简介: 汇编语言学习笔记 下

本文承接汇编语言学习笔记 上

上篇文章记录了汇编语言寄存器,汇编语言基本组成部分,数据传送指令,寻址指令,加减法指令,堆栈,过程,条件处理,整数运算的内容

image.gif编辑

高级过程

大多数现代编程语言在调用子程序的时候会把参数压入对战

子程序也常常把局部变量压入堆栈

    • 子程序在C和C++中被称为函数
    • 在Java中被称为方法
    • 在宏汇编程序(MASM)中被称为过程

    image.gif 编辑

    堆栈帧

    堆栈参数

    堆栈帧是一块堆栈保留区域

    存放

      • 被传递的实际参数
      • 子程序的返回值
      • 局部变量
      • 被保存的寄存器

      创建步骤

        1. 将被传递的实际参数压入堆栈
        2. 当子程序被调用时,该子程序的返回值压入堆栈
        3. 子程序开始执行的时候,EBP被压入堆栈
        4. 设置EBP等于ESP,EBP成为子程序所有参数的引用基址
        5. 如果有局部变量,修改ESP在堆栈中为其预留空间
        6. 需要保留的寄存器,将它们压入堆栈

        Fastcall调用方式

        顾名思义,是一种希望快速的调用方式

        我们来分析一下这个调用方式:

        调用自过程的时候,需要首先将参数传入EAX,EBX,ECX,EDX,少数情况还会传入ESI,EDI

        我们知道寄存器是CPU内部的原件,堆栈在内存上,寄存器调用明显更快

        但是我们知道通用寄存器很少,很多都有特定的功能,乘法需要用到EAX,还有许多寄存器用来循环数值和参与计算的操作数

        因此寄存器不可能一直存放传递给过程的参数

        在过程调用之前, 存放参数的寄存器需要首先入栈,然后向其分配过程参数

        但是这些额外的入栈操作会让代码变得混乱,还有可能消除性能优势

        值传递

        一个参数通过数值传递时,该值的副本会被压入堆栈

        .data
        val1 DWORD 3
        val2 DWORD 6
        .code
        push val2
        push val1
        call AddTwo

        image.gif

        引用传递

        通过引用来传递的参数包含的是对象的地址

        push OFFSET val2
        push OFFSET val1

        image.gif

        传递数组

        将数组的地址压入堆栈

        不愿意采用将每个数组元素压入堆栈的原因是这样很慢而且浪费堆栈空间

        访问堆栈的参数

        1.将传递的参数压入堆栈,调用子过程

        2.EBP寄存器存放的是原来栈帧的基址,我们需要现将EBP压入栈保存

        3.然后将当前的ESP作为新的栈帧的基址

        示例

        int AddTwo(int x,int y)
        {
            return x+y;
        }

        image.gif

        将EBP入栈,设置ebp位esp的值

        AddTwo PROC
            push ebp
            mov ebp,esp

        image.gif

        ADD(5,6)

        6

        [EBP+12]
        5 [EBP+8]
        返回地址 [EBP+4]
        EBP mov ebp,esp

        这样通过当前EBP和偏移量就能访问传入的参数和原来的ebp(返回地址)

        显式的堆栈参数

        堆栈参数的引用表达式形如[esp+8],称它们为显式的堆栈参数

        清除堆栈

        子程序返回时,必须将参数从堆栈中删除

        否则会导致内存泄露,堆栈会被破坏

        C调用方式-cdecl

        用于C和C++语言

        子程序的参数按逆序入栈

        解决了运行时堆栈的问题

        在调用子过程后,紧跟一条语句让堆栈指针ESP加上一个数,该数的值即为子程序参数所占的堆栈空间

        main PROC
            push 6
            push 5
            call AddTwo
            add esp,8
            ret
        main ENDP

        image.gif

        能将参数从堆栈中删除

        STDCALL调用规范

        给RET指令添加了一个参数,使程序在返回调用过程的时候,ESP会加上这个参数

        这个添加的整数和过程参数占用的堆栈空间字节数相等

        AddTwo PROC
            push ebp
            mov ebp,esp
            mov eax,[ebp+12]
            add eax,[ebp+8]
            pop ebp
            ret 8
        AddTwo ENDP

        image.gif

        局部变量

        在子过程中创建的变量

        局部变量在ebp下

        void Mysub()
        {
            int X=10;
            int Y=20;
        }

        image.gif

        每个变量的存储大小都要向上取整保存为4的倍数

        两个局部变量一共保留8个字节

        MySub PROC
            push ebp
            mov ebp,esp
            sub esp,8
            mov DWORD PTR [ebp-4],10
            mov DWORD PTR [ebp-8],20
            mov esp,ebp
            pop ebp
            ret
        MySub ENDP

        image.gif

        从堆栈中删除局部变量,只需要执行:

        mov esp,ebp

        image.gif

        esp向上移动=内存释放

        可以给局部变量的偏移量定义一个符号,在代码中使用这些符号

        X_local EQU DWORD PTR [ebp-4]
        Y_local EQU DWORD PTR [ebp-8]
        MySub PROC
            push ebp
            mov ebp,esp
            sub esp,8
            mov X_local,10
            mov Y_local ,20
            mov esp,ebp
            pop ebp
            ret
        MySub ENDP

        image.gif

        保存和恢复寄存器

        子程序在修改寄存器之前将它们的当前值保存到堆栈

        通常在ebp入栈,设置ebp等于esp之后,相关寄存器入栈

        栈帧

        解释说明
        传递的参数 [EBP+8]

        返回地址

        [EBP+4](原来栈帧的EBP)
        EBP

        当前栈帧的EBP

        ECX
        EDX 当前ESP指向的位置

        EBP被初始化之后,整个过程中它的值将保持不变

        ECX,EDX入栈并不影响EBP按照原来的偏移量访问传递的参数

        引用参数

        引用参数通常是基址-偏移量寻址方式进行访问

        每个引用参数都是一个指针

        .data
        count=100
        array WORD count DUP(?)
        .code
        push OFFSET array
        push count
        call ArrayFill

        image.gif

        ArrayFill PROC
            push ebp
            mov ebp,esp

        image.gif

        数组偏移量
        数组长度

        返回地址

        EBP

        LEA指令

        返回间接操作数的地址

        C代码:

        void makeArray()
        {
            char myString[30];
            for(int i=0;i<30;i++)
                myString[i]='*';
        }

        image.gif

        等效的汇编代码:

        makeArray PROC
            push ebp
            mov ebp,esp
            sub esp,32                ;mystring位于EBP-30的位置
            lea esi,[ebp-30]          ;加载mystring的地址
            mov ecx,30                ;设置循环计数器
        L1: mov BYTE PTR [esi],'*'    ;填充一个位置为'*'
            inc esi                   ;指向下一个元素
            loop L1                   ;循环30次,直到ecx是0
            add esp,32                ;恢复esp
            pop ebp
            ret
        makeArray ENDP

        image.gif

        ENTER指令

        为被调用过程自动创建堆栈帧

        包含三个操作

          • 把EBP入栈        push ebp
          • 把ebp设置为堆栈帧的基址        mov ebp,esp
          • 为局部变量保留空间          sub esp,numbytes

          ENTER有两个操作数,一个是常数,是局部变量保存的堆栈空间(字节),第二个参数定义了过程的词法嵌套级

          ENTER numbytes,nestinglevel

          MySub PROC
              enter 0,0

          image.gif

          等效于:

          MySub PROC
              push ebp
              mov ebp,esp

          image.gif

          MySub PROC
              enter 8,0

          image.gif

          等效于:

          MySub PROC
              push ebp
              mov ebp,esp
              sub esp,8

          image.gif

          LEAVE指令

          结束一个过程的堆栈帧,与ENTER是相对应的操作

          直接上代码理解

          MySub PROC
              enter 8,0
              .
              .
              leave
          MySub ENDP

          image.gif

          等效于:

          MySub PROC
              push ebp
              mov ebp,esp
              sub esp,8
              .
              .
              mov esp,ebp
              pop ebp
              ret
          MySub ENDP

          image.gif

          前一篇文章汇编语言学习笔记 上

          已将基本的汇编语言语法总结了一遍

          暂时不更新

          image.gif编辑

          未完待续

          相关文章
          |
          3月前
          |
          程序员 存储 安全
          【汇编】汇编语言的介绍
          【汇编】汇编语言的介绍
          【汇编】汇编语言的介绍
          |
          5月前
          |
          安全 Java 大数据
          汇编语言的不同
          汇编语言的不同
          36 0
          |
          8月前
          |
          存储 安全 程序员
          5.1 汇编语言:汇编语言概述
          汇编语言是一种面向机器的低级语言,用于编写计算机程序。汇编语言与计算机机器语言非常接近,汇编语言程序可以使用符号、助记符等来代替机器语言的二进制码,但最终会被汇编器编译成计算机可执行的机器码。相较于高级语言(如C、Python等),汇编语言学习和使用难度相对较大,需要对计算机内部结构、指令集等有深入的了解,以及具有良好的编程习惯和调试能力。但对于需要对计算机底层进行操作的任务,汇编语言是极其高效的,因为其可以实现对计算机底层资源的精细控制,极大地提高了计算机运行效率。
          63 0
          |
          10月前
          |
          缓存 前端开发 Java
          汇编语言简介
          汇编语言(assembly language)是一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。在汇编语言中,用助记符(Mnemonics)代替机器指令的操作码,用地址符号(Symbol)或标号(Label)代替指令或操作数操作数的地址。在不同的设备中,汇编语言对应着不同的机器语言指令集,通过汇编过程转换成机器指令。普遍地说,特定的汇编语言和特定的机器语言指令集是一一对应的,不同平台之间不可直接移植。
          |
          11月前
          【8086汇编】《汇编语言(第三版)》实验一
          需要用到的指令✨✨ 查看、修改CPU中寄存器的内容:R命令 查看内存中的内容:D命令 修改内存中的内容:E命令(可以写入数据、指令,在内存中,它们实际上没有区别) 将内存中的内容解释为机器指令和对应的汇编指令:U命令 执行CS:IP指向的内存单元处的指令:T命令 以汇编指令的形式向内存中写入指令:A命令
          |
          12月前
          |
          存储 编译器 C语言
          计算机底层知识之汇编语言
          汇编语言和本地代码是一一对应的 推荐阅读指数⭐️⭐️⭐️⭐️⭐️ 不会转换成本地代码的伪指令 推荐阅读指数 ⭐️⭐️⭐️ 汇编语言的语法是操作码 + 操作数 推荐阅读指数⭐️⭐️⭐️⭐️⭐️ mov指令 推荐阅读指数 ⭐️⭐️⭐️ 对栈进行push 和 pop 推荐阅读指数 ⭐️⭐️⭐️ 函数调用机制 推荐阅读指数 ⭐️⭐️⭐️⭐️⭐️ 函数内部的处理 推荐阅读指数 ⭐️⭐️⭐️⭐️⭐️ 全局变量用的内存空间 推荐阅读指数 ⭐️⭐️⭐️ 循环处理的实现方法 推荐阅读指数 ⭐️⭐️⭐️⭐️⭐️
          计算机底层知识之汇编语言
          |
          缓存 前端开发 rax
          汇编语言学习 上
          本文是介绍汇编语言的基本组成和基本齐全的指令,以及帮助理解这些的背景知识 包括寄存器,汇编语言基本组成部分,数据传送指令,寻址指令,加减法指令,堆栈,过程,条件处理,整数运算
          113 0
          汇编语言学习 上
          |
          存储 程序员 C语言
          【汇编语言王爽】学习笔记p54-p79(下)
          【汇编语言王爽】学习笔记p54-p79
          81 0
          【汇编语言王爽】学习笔记p54-p79(下)
          |
          C语言 Perl
          【汇编语言王爽】学习笔记p54-p79(上)
          【汇编语言王爽】学习笔记p54-p79
          86 0
          【汇编语言王爽】学习笔记p54-p79(上)
          |
          C语言
          【汇编语言王爽】学习笔记-p40-p54
          【汇编语言王爽】学习笔记-p40-p54
          68 0
          【汇编语言王爽】学习笔记-p40-p54