汇编语言之寄存器(内存访问)2

简介: 汇编语言之寄存器(内存访问)2

7、cpu提供的栈机制

现今的CPU中都有栈的设计。8086CPU提供的入栈和出栈指令,最基本的两个是push(入栈)和pop(出栈)。比如:


Push ax 表示将寄存器ax中的数据送入栈中,pop ax 表示从栈顶取出数据送入ax。8086CPU的入栈和出栈操作都是以字为


单位进行的。


下面两张图描述了push和pop指令的执行过程。

2.png上面两张图指令的执行过程,写成代码如下:


Mov ax, 123H


Push ax


Mov bx, 2266H


Push bx


Mov cx, 1122H


Push cx


Pop ax


Pop bx


Pop cx


注意:字型数据用两个内存单元存放,高地址单元存放高8位,低地址单元存放低8位。


看了上面两张图后,现在提出两个问题。问题1:我们将10000H~1000FH这段内存当作栈来使用,CPU是如何知道这段空


间是栈?关于这个问题将在3.10节解答。


问题2:push ax等入栈指令执行时,要将寄存器中的数据放入当前栈顶单元的上方,成为新的栈顶元素;pop ax等指令执


行时,要从栈顶单元取出数据送入寄存器中。显然,push、pop在执行的时候,CPU必须要知道哪个单元是栈顶单元,可是,如


何知道?


答:8086CPU中,有两个寄存器,堆栈段寄存器SS,堆栈指针寄存器SP,栈顶的段地址存放在SS中,偏移地址存放在


SP中,任意时刻,SS:SP指向栈顶元素,push和pop指令在执行时,CPU从SS和SP中得到栈顶单元的地址。


现在,我们可以完整地描述push和pop指令的功能了,例如:push ax。push ax的执行,由以下两步完成:


1. SP=SP-2,SS:SP指向当前栈顶前面的单元,以当前栈顶前面的单元为新的栈顶。


2. 将ax中的数据送入SS:SP指向的内存单元处,SS:SP此时指向新栈顶。


下图描述了push ax的执行过程。


3.png

3.png

将10000H~1000FH这段空间当作栈段,SS=1000H,栈空间大小为16字节,栈最底部的字单元地址为1000:000E,任


意时刻,SS:SP指向栈顶,当栈中只有一个元素的时候,SS=1000H,SP=000EH,栈为空,就相当于栈中唯一的元素出栈后,


SP=SP+2,原来为000EH,加2后SP=0010H,所以,当栈为空的时候,SS=1000H,SP=0010H。


换一个角度看,任意时刻,SS:SP指向栈顶元素,当栈为空的时候栈中没有元素,也就不存在栈顶元素,所以SS:SP只能指


向栈的最底部单元下面的单元,该单元的偏移地址为栈最底部的字单元的偏移地址+2,栈最底部字单元的地址为1000:000E,


所以,栈空时,SP=0010H。


接下来,我们描述pop指令的功能,例如:pop ax。Pop ax的执行过程和push ax刚好相反,由以下两步完成:


1. 将SS:SP指向的内存单元处的数据送入ax中。


2. SP=SP+2,SS:SP指向当前栈顶下面的单元,以当前栈顶下面的单元为新的栈顶。


下图描述了pop ax的执行过程。


4.png

4.png

注意:上图中,出栈后,SS:SP指向新的栈顶1000EH,pop操作前的栈顶元素,1000CH处的数据2266H依然存在,但


是,它已不在栈中,当再次执行push等入栈指令后,SS:SP移至1000CH,并在里面写入新的数据,将它覆盖。


8、push指令 pop指令

Push和pop指令的格式有如下两种形式:


第一种形式:push 寄存器    ;将一个寄存器中的数据入栈。


           Pop 寄存器    ;出栈,用一个寄存器接收出栈的数据。


这一种形式,它们可以在栈和寄存器之间传送数据。


注意:上面的寄存器可以是段寄存器,比如,可以是:push ds、pop ds。


第二种形式:push 内存单元    ;将一个内存单元中的字型数据入栈(注意,栈操作都是以字为单位)。


           Pop 内存单元    ;出栈,用一个内存字单元接收出栈的数据。


比如:mov ax, 1000H


     Mov ds, ax    ;将内存单元的段地址放在DS中。


     Push [2a38]    ;将内存单元[2a38]中的字型数据入栈。


     Pop [2a3a]    ;出栈,出栈的数据送入内存单元[2a3a]。


这一种形式,它们可以在栈和内存单元之间传送数据。


指令执行时,CPU要知道内存单元的地址,可以在push、pop指令中给出内存单元的偏移地址,段地址在指令执行时,CPU


从DS中取得。


Push和pop实质上是一种内存传送指令,与mov指令不同的是,push和pop指令访问的栈空间的地址不是在指令中给出


的,而是由SS:SP指出的。同时,push和pop指令还要改变SP中数值。Mov指令只需一步操作,就是传送,而执行push、


Pop指令需要两步操作,执行push时,先改变SP,后向SS:SP处传送;执行pop时,先读取SS:SP处的数据,后改变SP。


9 、 栈段

前面讲过(参见2.7节),对于8086PC机,在编程时,可以根据需要,将一组内存单元定义为一个段。我们可以将长度为N


(N≤64KB)的一组地址连续、起始地址为16的倍数的内存单元,当作栈空间来用,从而定义了一个栈段。


比如,我们将10010H~1001FH这段内存空间当作栈来用,以栈的方式进行访问,这段空间就可以认为是一个栈段,大小为


16个字节。


如何使得如push、pop等栈操作指令访问我们定义的栈段呢?那就是要将SS:SP指向我们定义的栈段。


现在我们来回答3.8节中的第一个问题。答:只要这段内存单元被SS:SP指向,那么,CPU就会把这段空间当作栈来使用。


相关文章
|
14天前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
40 4
|
29天前
|
缓存 算法 数据处理
如何选择合适的内存访问模式
【10月更文挑战第20天】如何选择合适的内存访问模式
42 1
|
30天前
|
存储 容器
内存越界访问(Out-of-Bounds Access)
【10月更文挑战第12天】
143 2
|
30天前
|
Rust 编译器
|
2月前
|
存储 网络协议 大数据
一文读懂RDMA: Remote Direct Memory Access(远程直接内存访问)
该文档详细介绍了RDMA(远程直接内存访问)技术的基本原理、主要特点及其编程接口。RDMA通过硬件直接在应用程序间搬移数据,绕过操作系统协议栈,显著提升网络通信效率,尤其适用于高性能计算和大数据处理等场景。文档还提供了RDMA编程接口的概述及示例代码,帮助开发者更好地理解和应用这一技术。
|
2月前
|
存储 安全 Linux
将文件映射到内存,像数组一样访问
将文件映射到内存,像数组一样访问
31 0
|
2月前
ARM64技术 —— MMU处于关闭状态时,内存访问是怎样的?
ARM64技术 —— MMU处于关闭状态时,内存访问是怎样的?
|
3月前
|
存储 编译器 C语言
【C语言篇】数据在内存中的存储(超详细)
浮点数就采⽤下⾯的规则表⽰,即指数E的真实值加上127(或1023),再将有效数字M去掉整数部分的1。
381 0
|
28天前
|
存储 C语言
数据在内存中的存储方式
本文介绍了计算机中整数和浮点数的存储方式,包括整数的原码、反码、补码,以及浮点数的IEEE754标准存储格式。同时,探讨了大小端字节序的概念及其判断方法,通过实例代码展示了这些概念的实际应用。
59 1
|
1月前
|
存储
共用体在内存中如何存储数据
共用体(Union)在内存中为所有成员分配同一段内存空间,大小等于最大成员所需的空间。这意味着所有成员共享同一块内存,但同一时间只能存储其中一个成员的数据,无法同时保存多个成员的值。