汇编语言学习第三章-寄存器(内存访问)

2024-08-25 05:18

本文主要是介绍汇编语言学习第三章-寄存器(内存访问),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  本博文系列参考自<<汇编语言>>第三版,作者:王爽


本章将紧接着上一章从内存访问的角度讲解寄存器。


3.1 内存中字的存储

       一个字的大小为两个字节,8086CPU一个寄存器的大小为两个字节,所以使用8086CPU的寄存器存储一个字单元的时候,高字节寄存器存储字的高位字节,低字节寄存器存储字的低位字节。类似的,我们在用内存存储一个字的时候,高内存单元存储字的高字节,低内存单元存储字的低字节。比如20000(4E20H)在进行内存存储的时候,我们此时有0,1两个地址的内存单元,那么字的高字节4EH存储在内存地址为1的内存单元,字的低字节单元20H存储在内存地址为0的低内存单元。如下图所示:


字单元概念,即连续存储两个字节的内存单元。高内存单元存储字的高字节数据,低内存单元存储字的低字节数据。以后将起始地址为N的字节单元称为N地址字单元。


3.2 DS和[address],字的传送

CPU要读取一个内存单元的地址,必须得到该内存单元的段地址:偏移地址 才能得到实际的内存地址。我们如果我们要将读取内存地址为10000H的数据到AL,那么有如下的代码段:

      尽管我们之前可能没学过如果进行内存访问,我们不能看出要访问10000H内存单元即需要访问 1000:0其中1000H为段地址,0H为偏移地址。mov指令我们是学过的,前两句bx,1000H和mov ds,bx我们可以猜测其意思是将1000H存入寄存器ds中,那么为何不能直接通过mov ds,1000H直接赋值呢,这里有个问题是因为DS为段寄存器,8086CPU所以不能直接给段寄存器复制,必须通过普通寄存器过渡存储。那么 mov al,[0]就是我们访问内存10000H数据的,那么这里[0]我们推测是偏移地址,那么段地址来自于哪里呢,显然8086CPU对于段地址默认取自DS寄存器。所以这样不仅有了段地址和偏移地址,我们就可以轻松取得内存10000h的数据了,这里内存地址表示方式为[......],表示取得方框内为偏移地址的内存中的数据。

关于寄存器和内存之间传值,因为8086CPU在内存中有16根数据线,故一次性可以传送一个字的数据。


3.4 mov、add、sub指令,数据段

关于mov传值的形式:

mov 寄存器,数据        如:mov ax,8

mov 寄存器,寄存器    如: mov ax,bx

mov 寄存器,内存单元   如:mov ax,[0]

mov 内存单元,寄存器   如:mov [0],ax

mov 段寄存器,寄存器   如:mov DS,AX


mov 寄存器,段寄存     如:mov AX,DS

mov 内存单元,段寄存器 如:mov [0],DS

mov 段寄存器,内存单元 如:mov DS,[0]


add与sub指令的形式与mov类似,如下:




在8086CPU中我们可以把一段连续的内存地址作为数据段使用,该数据段用于存储数据。比如将10000H-10006定义为数据段,我们要取该段数据段的时候将段寄存器DS存入1000H,即可访问该段内存的地址,比如我们要将三个内存空间数据叠加,比如三个内存空间为10002H,10003H,10005H,代码如下:

mov ax,1000H

mov  ds,ax

mov al, 0;

add al, [2];

add al, [3];

add al. [5];



3.5 栈结构及CPU提供的栈机制

栈为一种线性结构,这里我们可以理解为栈为一种先进后出的存储结构或者数据结构。举个例子,比如我们有三本书book1,book2和book3 依次入栈。其结构及入栈出栈流程如下:

栈空:    |              |栈顶

           |              |

   |              | 栈低  

入栈:          

放入book1:    |                 |栈顶

             |                 |

     |    book1    | 栈低


放入book2:    |                 |栈顶

              |    book2    |

     |    book1   | 栈低


放入book3:    |    book3   |栈顶

              |    book2   |

     |    book1   | 栈低

出栈:

取出book3:    |                 |栈顶

              |    book2    |

     |    book1    | 栈低


放入book2:    |                 |栈顶

              |                |

     |    book1   | 栈低


放入book1:    |                |栈顶

              |                |

     |                | 栈低

在8086CPU也提供了相关指令以栈的方式访问内存,在基于8086CPU编程的时候。可以将一段内存当做栈使用,8086CPU指令系统提供了PUSH和POP两个指令进行栈操作,PUSH为入栈操作,POP为出栈操作,入栈时将数据压栈,出栈的时候取出栈顶指向的数据。8086CPU的PUSH和POP操作都是以字为单位进行的。比如PUSH ax为将ax的数据压入栈空间,POP ax为将栈顶的数据弹出存入ax中。

下面将10000H-1000FH这段内存当成栈空间使用,其相关出栈入栈的流程如下图所示:


图中对栈的整个操作流程很清楚了,那么问题来了,CPU如何知道这段内存按照栈的方式进行存储,另外我们在压栈和出栈的过程中都是压入栈顶和弹出栈顶元素,那么这个栈顶位置保存在何处呢。其实CPU已经为我们考虑好了,在8086CPU中有两个重要的寄存器,SS和SP,SS即Stack Segment,SP即Stack Point,代表着栈的段地址和栈顶地址。通过这两个地址CPU便可以识别栈空间和栈顶位置。


现在从新描述PUSH和POP指令的运行过程:

例如PUSH AX,由两步完成

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

(2) 将AX送入SS:SP指向的内存单元处,SS:SP此时指向新的栈顶。

例如POP AX,由两步完成

(1) 将SS:SP指向的内存单元处的数据送入AX中。

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


3.6 栈顶越界的问题

从上面的描述已经介绍了SS和SP指向栈空间栈顶的位置,但是栈空间是有大小的,那么如果一直将数据压栈直到超过栈的空间那就会造成栈顶越界的问题,实际上CPU是不会检查栈顶是否越界的问题,因为CPU并不知道当前栈空间的大小,所有在编程的时候需要程序员自己注意和控制栈顶越界的问题。


3.7 PUSH和POP的其他使用方式和栈段

PUSH和POP是对栈存储空间操作的特定指令,然而PUSH和POP不仅可以操作寄存器还可以对段寄存器和内存进行操作

比如 PUSH DS;

POP   DS;

PUSH [0];

POP  [0];

关于段,前面我们已经接触过好几个段寄存器,CS,DS,SS其中CS为code segment(代码段),DS为data segment(数据段),ss为stack segment(栈段),这三个段寄存器分别存储不同的数据。在需要的时候可以通过段地址+偏移地址取得各个段中的数据。


OK,以上内容即为寄存器的进一步讲解。下一篇博客将开始介绍第一个汇编程序。

 


          




这篇关于汇编语言学习第三章-寄存器(内存访问)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1104641

相关文章

关于Java内存访问重排序的研究

《关于Java内存访问重排序的研究》文章主要介绍了重排序现象及其在多线程编程中的影响,包括内存可见性问题和Java内存模型中对重排序的规则... 目录什么是重排序重排序图解重排序实验as-if-serial语义内存访问重排序与内存可见性内存访问重排序与Java内存模型重排序示意表内存屏障内存屏障示意表Int

SpringBoot实现基于URL和IP的访问频率限制

《SpringBoot实现基于URL和IP的访问频率限制》在现代Web应用中,接口被恶意刷新或暴力请求是一种常见的攻击手段,为了保护系统资源,需要对接口的访问频率进行限制,下面我们就来看看如何使用... 目录1. 引言2. 项目依赖3. 配置 Redis4. 创建拦截器5. 注册拦截器6. 创建控制器8.

SpringBoot如何访问jsp页面

《SpringBoot如何访问jsp页面》本文介绍了如何在SpringBoot项目中进行Web开发,包括创建项目、配置文件、添加依赖、控制层修改、测试效果以及在IDEA中进行配置的详细步骤... 目录SpringBoot如何访问JSP页python面简介实现步骤1. 首先创建的项目一定要是web项目2. 在

如何测试计算机的内存是否存在问题? 判断电脑内存故障的多种方法

《如何测试计算机的内存是否存在问题?判断电脑内存故障的多种方法》内存是电脑中非常重要的组件之一,如果内存出现故障,可能会导致电脑出现各种问题,如蓝屏、死机、程序崩溃等,如何判断内存是否出现故障呢?下... 如果你的电脑是崩溃、冻结还是不稳定,那么它的内存可能有问题。要进行检查,你可以使用Windows 11

Linux限制ip访问的解决方案

《Linux限制ip访问的解决方案》为了修复安全扫描中发现的漏洞,我们需要对某些服务设置访问限制,具体来说,就是要确保只有指定的内部IP地址能够访问这些服务,所以本文给大家介绍了Linux限制ip访问... 目录背景:解决方案:使用Firewalld防火墙规则验证方法深度了解防火墙逻辑应用场景与扩展背景:

Python使用pysmb库访问Windows共享文件夹的详细教程

《Python使用pysmb库访问Windows共享文件夹的详细教程》本教程旨在帮助您使用pysmb库,通过SMB(ServerMessageBlock)协议,轻松连接到Windows共享文件夹,并列... 目录前置条件步骤一:导入必要的模块步骤二:配置连接参数步骤三:实例化SMB连接对象并尝试连接步骤四:

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

NameNode内存生产配置

Hadoop2.x 系列,配置 NameNode 内存 NameNode 内存默认 2000m ,如果服务器内存 4G , NameNode 内存可以配置 3g 。在 hadoop-env.sh 文件中配置如下。 HADOOP_NAMENODE_OPTS=-Xmx3072m Hadoop3.x 系列,配置 Nam

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06