汇编(五)栈、CPU提供的栈机制、push、pop指令

简介: 汇编、栈、CPU提供的栈机制、push、pop指令、编程、汇编语言

3.6 栈

  • 栈是一种具有特殊的访问方式的存储空间,他的特殊性就在于 最后一个进入这个空间的数据,是最先出去的
  • 栈有两种基本的操作:入栈和出栈

      1. 入栈:将一个新的元素放到栈顶
      2. 出栈:从栈顶取出一个元素
    • 栈顶元素总是最后一个入栈的,需要出的时候,又会是第一个被取出的
    • 操作规则:LIFO

      • (Last in first out) 后进先出

3.7 CPU提供的栈机制

  • 现今的CPU都有栈的设计, CPU提供相关的指令来以栈的方式访问内存空间
  • 这就意味着,我们再CPU编程的时候,可将一段内存当做栈来使用

    push(入栈):

    • push ax: 将寄存器ax中的数据送入栈中

    pop(出栈):

    • pop ax:从栈顶取出数据送入ax中
    入栈和出栈的操作都是以 字 为单位进行的
  • 字型数据用两个单元存放,高地址单元放高8位,低地址单元房地8位
  • _
1. CPU如何知道一段内存空间被当做栈使用?
  • 有两个寄存器:

    • 段寄存器:SS 存放栈顶的段地址
    • 寄存器:SP 存放栈顶的偏移地址
  • 任意时刻 SS:SP指向栈顶元素
2. 执行push和pop的时候,如何知道那个单元是栈顶单元的?

push_

  • push ax
    1. 先进行:SP = SP - 2
    2. 然后将ax中的内容送入SS:SP指向的内存单元处,SS:SP此时指向新的栈顶

pop_

  • pop ax
    1. 先将栈顶(SS:SP)数据拿出来给ax
    2. 然后:SP = SP + 2

知识点:

  • 当pop之后其实栈中的数据还是存在的但是并不属于栈中内内容了、不能操作、当下一次push的时候回将其进行覆盖,并没有一个真正的删除,和硬盘格式化之后还可以恢复是一个道理,只是改变的指针的指向
  • 如果将10000~1000F作为栈的空间:初始转态的栈是空的,此时:

    • ss=1000
    • sp=0010(F的高一位地址 )
    • 栈空间大小为16个字节,栈最底部的字节单元地址为 1000:000E
    • 任意时刻 SS:SP指向栈顶,当栈中只有一个元素的时候:

      **SS=1000,SP=000E**
    • 栈为空,就相当于栈中唯一的元素被pop,出栈后,SP=SP+2,SP原来为000E,加2后SP=10
    • 所以当栈为空的时候,SS=1000,SP=10
  • 换个角度说:
    1. 任意时刻,SS:SP指向栈顶元素,当栈为空时候,栈中没有元素,也就不存在栈顶元素
    2. 所以SS:SP只能指向栈的最底部单元下面的单元,该单元中的偏移地址为栈最底部的字节单元的偏移地址+2
    3. 栈最底部字单元的地址为1000:000E,所以栈为空时 SP=000E-2=0010
    4. 只有栈内有元素的时候才有栈顶,否则不存在栈顶

3. CPU如何知道当前要执行的指令所在的位置?
  • 寄存器cs和ip中存放着当前执行的段地址和偏移地址

3.8 栈顶超界的问题

_

  • SS和SP只记录了栈顶的地址,依靠SS和SP可以保证在入栈和出栈是找到栈顶
  • 当栈满的时候再使用push指令入栈,栈空的时候在pop指令出栈都会发证栈顶超界的问题。 栈顶越界是危险的,因为会覆盖掉其他数据
  • 因为我们既然将一段空间安排为栈,那么在栈空间之外的空间里很可能存放了一些具有其他用途的数据、代码等、这些数据、代码可能使我们自己程序中的、也有可能是别的程序中的、如果是系统关键内容就危险了
  • 但是由于我们在入栈时的不小心而将这些数据、代码意外的改写、都会引发一连串的错误。我么当然希望CPU可以帮我们解决这个问题
  • 可是,如何保证在入栈,出栈时,栈顶不会超出栈空间?

    • 其实CPU在执行的时候只考虑两种情况

      1. 当前栈顶在何处
      2. 当前执行的指令是那一条
    • 结论:

      • 我们再编程的时候要看自己操心栈的超界问题,要根据可能用到的最大栈空间,来安排栈的大小,防止入栈的数据太多而导致的超界了;
      • 执行出栈操作的时候也要注意,以防栈空的时候继续出栈而导致超界

3.9 push、pop指令

  • push指令和pop指令是可以在寄存器和内存之间传送数据的

    栈与内存:
    • 栈空间当然也是内存空间的一部分,它是一段可以以一种特殊方式进行访问的内存空间
    • 栈只是一种数据结构的存放格式
  • push和pop的指令格式(1)

      1. push 寄存器:将一个寄存器的数据入栈
      2. pop 寄存器: 出栈,用一个寄存器接受出栈的数据
    • 如:

      • push ax
      • pop bx
  • push和pop的指令格式(2)

      1. push 段寄存器:将一个段寄存器的数据入栈
      2. pop 段寄存器:出栈, 用一个段寄存器接受出栈的数据
    • 如:

      • push ds
      • pop es
  • push和pop的指令格式(3)

      1. push 内存单元:将一对内存单元的数据入栈(栈操作都是以字为单位的)
      2. pop 内存单元:出栈, 用一对内存单元接受出栈的字单元数据
    • 如:

      • push [0]
      • pop [2]
  • 执行指令时,CPU要知道内存单元的地址,可以在push,pop指令中给出内存单元的偏移地址,段地址是在指令执行时,CPU从ds中自动获取的

    段寄存器都是以S结尾的,通用寄存器都是以X结尾的

    • 段地址在执行时可以从DS获得
    • 数据的段地址永远是从DS获得
    • 代码的段地址永远是从CS中获得
    • 栈的段地址永远是从SS中获得
  • 3_7_
  • # 设置栈的段地址,ss=1000,不能直接向段寄存器送入数据,要通过ax通用寄存器传递
    mov ax, 1000
    mov ss, ax
    # 设置栈顶的偏移地址,因为栈为空,所以sp=0010
    mov sp, 0010
    # 压入数据
    push ax
    push bx
    push ds
  • 3_8_
  • mov ax, 1000
    mov ss, ax
    mov sp, 0100
    mov ax=001a
    mov bx=001b
    push ax
    push bx
    sub ax, ax
    sub bx, bx
    pop bx
    pop ax
  • 从上面的程序可以看到,用栈来暂存以后需要恢复的寄存器中的内存时,出栈的顺序要和入栈的顺序相反, 因为最后入栈的寄存器的内容在栈顶,所以在恢复时,是最先出栈的
  • 3_9_
  • mov bx, 1000
    mov ss, bx
    mov ap, 10
    mov ax, 002a
    mov bx, 002b
    push ax
    push bx
    pop ax
    pop bx
  • 3_10_
  • mov ax, 1000
    mov ss, ax
    mov sp, 2
    mov ax, 226
    push, ax
  • Pop、和push实际上就是一种内存传送指令,可以在寄存器和内存之间传送数据,与mov指令不同的是 push和pop指令访问的内存单元的地址不是在指令中给出,而是ss:p指出的
  • 我们需要是十分清楚的是,push和pop指令同mov指令不同, CPU执行mov指令只需要一步, 而执行push、pop指令却需要两步操作
  • 执行push时:

    • 先改变sp,后向ss:sp压入
  • 执行pop时:

    • 先读取ss:sp处的数据, 后改变sp
  • push、pop指令修改的只是sp,也就是说栈顶的变化范围最大为:0~FFFF(SP寄存器的大小)
  1. 在ss:sp中存放栈顶的段地址和偏移地址, 提供入栈和出栈指令, 他们根据ss:sp指示的地址, 按照栈的方式访问内存单元
  2. 任意时刻。ss:sp执行栈顶元素
  3. 8086CPU只记录栈顶, 栈空间的大小我们要自己管理
  4. 用栈来暂存以后需要恢复的寄存器的内容, 寄存器出栈的顺序要和 入栈相反

    • 栈是一种非常重要的机制, 一定要深入理解, 灵活掌握
相关文章
|
4月前
|
存储 缓存 程序员
软考软件评测师——计算机组成与体系结构(CPU指令系统)
本内容详细解析了计算机中央处理器(CPU)的核心架构及其关键组件的工作原理。首先介绍了CPU的四大核心模块:运算单元、控制单元、寄存器阵列和内部总线,并阐述其在数据处理中的核心职责。接着深入探讨了算术逻辑部件(ALU)的功能与专用寄存器的作用,以及通用寄存器对性能提升的意义。随后分析了控制单元的指令处理流程及特殊寄存器的功能。此外,还解析了寄存器系统的分类与设计特点,并对比了不同内存访问模式的特点与应用场景。最后,通过历年真题巩固相关知识点,帮助理解CPU各组件的协同工作及优化策略。
|
12月前
CPU的工作原理基于其内部结构,通过执行指令来完成各种任务
CPU的工作原理基于其内部结构,通过执行指令来完成各种任务
312 3
|
11月前
|
存储 人工智能 编译器
【AI系统】CPU 指令集架构
本文介绍了指令集架构(ISA)的基本概念,探讨了CISC与RISC两种主要的指令集架构设计思路,分析了它们的优缺点及应用场景。文章还简述了ISA的历史发展,包括x86、ARM、MIPS、Alpha和RISC-V等常见架构的特点。最后,文章讨论了CPU的并行处理架构,如SISD、SIMD、MISD、MIMD和SIMT,并概述了这些架构在服务器、PC及嵌入式领域的应用情况。
709 5
|
12月前
|
存储 移动开发 C语言
【ARM汇编速成】零基础入门汇编语言之指令集(三)
【ARM汇编速成】零基础入门汇编语言之指令集(三)
275 0
|
12月前
|
编译器 C语言 计算机视觉
【ARM汇编速成】零基础入门汇编语言之指令集(二)
【ARM汇编速成】零基础入门汇编语言之指令集(二)
1015 0
|
存储 机器学习/深度学习 芯片
8086 汇编笔记(十二):int 指令 & 端口 & 直接定址表
8086 汇编笔记(十二):int 指令 & 端口 & 直接定址表
|
28天前
|
缓存 人工智能 算法
不同业务怎么选服务器?CPU / 内存 / 带宽配置表
本文详解了服务器三大核心配置——CPU、内存、带宽,帮助读者快速理解服务器性能原理。结合不同业务场景,如个人博客、电商、数据库、直播等,提供配置选择建议,并强调合理搭配的重要性,避免资源浪费或瓶颈限制。内容实用,适合初学者和业务选型参考。
272 0
|
1月前
|
存储 消息中间件 缓存
从纳秒到毫秒的“时空之旅”:CPU是如何看待内存与硬盘的?
在数据爆炸的时代,如何高效存储与管理海量数据成为系统设计的核心挑战。本文从计算机存储体系结构出发,解析B+树、LSM树与Kafka日志结构在不同数据库中的应用与优化策略,帮助你深入理解高性能存储背后的原理。
65 0