IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 汇编学习教程:访问内存(1) -> 正文阅读

[嵌入式]汇编学习教程:访问内存(1)

引言

哈喽大家好,在这里首先祝大家:新年快乐,虎年大吉~~新的一年里,祝小伙伴们的工作蒸蒸日上,生活和和美美!

OK,下面开始我们本篇汇编学习教程。在上篇博文中,我们分析了本书中的第一个实验,针对实验的现象和问题探究,明白了对于8086PC机中内存正确分布方式,同时也加深了Debug工具的使用印象。那么本篇博文中,我们将正式开启CPU对于内存的访问学习,重点讲述我们之前说到的段寄存器:DS、SS,这两个寄存器的使用和意义。

内存中字的存储

我们通过之前的学习了解到,CPU中使用寄存器来存储数据,8086CPU是十六位寄存器,所以它的寄存器可存放一个字。对于内存而言,由一个个内存单元组成,每个单元存储一个字节的数据,一个字是两个字节,那么在内存中存放一个字,则需要两个内存单元,而这两个内存单元遵守高位对应高位,低位对应低位规则!

什么是“高位对应高位,低位对应低位”?这里举一个例子,比如:我们将20000(十六进制4E20H)这个数据存放到内存单元0开始的内存中,会是什么样子?如图所示:

我们发现,数字20000,十六进制4E20H,在内存中分布,0下标对应“20H”,1下标对应“4EH”。对于 4E20H 来说,20H是它的低位,4EH是它的高位;对于内存空间来说,0下标属于低位,1下标属于高位,根据“高位对应高位,低位对应地位”分布规则,则0下标存储对应数据的低位,所以 0->20H ,1下标存储对应数据的高位,所以 1->4EH。

总结一下,高位对应高位,这两个高位分别指数据的高位和内存空间的高位;低位对应低位,这两个低位分别指数据的低位和内存空间的低位

易混淆点1

这里出现第一个易混淆点:容易搞错寄存器中和内存中,一个字中的两个字节顺序。

我们发现,由于“高位对应高位,低位对应低位”规则,寄存器中的一个字,和内存中一个字,阅读顺序是相反的,这就导致很容易出现数据阅读错误。

比如数据 4E20H,在AX寄存器中存放,形式为“4E20H”,符合我们的习惯认知;数据放到内存中,使用0,1两个内存单元存放,按照我们的阅读习惯,则是“204EH”,这样与原数据两个字节顺序正好相反!

克服该易出错点的方法其实很简单,一定要死命牢记分布规则:高位对应高位,低位对应低位!

易混淆点2

内存中所谓的低位和高位,是相对而言的,不存在固定的单元它就是低位或者高位。

比如,我们使用内存单元0、1来存储数据 4E20H,此时,对于内存单元0、1来说,0是低位,1是高位。我们换一下,使用内存单元1、2来存储数据 4E20H,那么此时对于内存单元1、2来说,1是低位,而2是高位,所以就变成了1单元存储20H,2单元存储4EH。

那么问题就来了,到底什么时候我们才能确定这是低位这是高位呢?答案就是根据实际程序运行而定

比如代码中CPU需要从内存地址2000:0处读取一个字的数据到寄存器AX中,则此时地址单元 2000:0 是低位,该单元的字节数据放入AX寄存器中低位,2000:1 是高位,该单元的字节数据放入AX寄存器中高位。

DS段寄存器

DS是CPU中的一个段寄存器,全称:Data Segment.。

我们都知道Data是数据,所以DS的功能和作用和数据是脱不了干系。还记得CS段寄存器么?我们说过CS段寄存器中存放的是代码段的段地址,配套的还有一个IP寄存器用来存放代码段的偏移地址,两者CS:IP加在一起,指向了内存中的代码数据。

在讲段寄存器的时候我们有说过,对于一个程序来说,最重要的有两大块:1、逻辑代码;2、各种声明的变量。我们可以这样说,代码和变量组成了一个程序。在实际的开发中,我们通常会在代码中写好各种标量的声明,所以会变相的认为变量实际上是代码的一部分,这种想法其实是错误的。CPU执行程序,是严格将两者分割开来的,程序中的代码告诉了CPU如何执行如何操作,而程序中的变量就是CPU需要执行操作的数据。

CS:IP指明了代码,那么变量则由DS来指明。

与CS不同的是,DS段寄存器中存放的是数据段的段地址,任意时刻CPU将DS中地址下的数据当作真实数据来看待处理。

访问内存

我们都知道CPU的寻址方式是基地址加偏移地址得到目的地址,DS只给出数据段的段地址肯定是无法完成寻址,必然需要给出一个偏移地址才能进行寻址读取。下面我们将通过一个例子来进行内存的读取:

例如我们读取内存地址单元10000H下的数据到寄存器AL中。

首先我们确定目的地址为:1000:0,段地址为1000H,也就是说DS寄存器中存放的数据为1000H,我们可以使用MOV指令来设置DS寄存器值。

偏移地址为0则使用:[0]来表示。整体代码如下:

mov bx,1000H
mov ds,bx
mov al,[0]

上述三条指令执行完毕后,会将内存地址单元10000H下的数据放入AL中。

首先我们说前两条指令。

我们使用了两条MOV指令来给DS段寄存器赋值,为什么要这么做?MOV可不可以直接给DS段寄存器赋值?比如我们直接 mov ds,1000H??

答案是当然不可以。因为DS是段寄存器,8086CPU不支持将数据直接送入段寄存器操作,所以 mov ds,1000H 是非法指令,无法执行。只能通过一个通用寄存器,先把数据赋值给通用寄存器,然后再由通用寄存器赋值给段寄存器,通过这种间接的方式来给段寄存器赋值。

下面说下最后一条指令:mov al,[0]

[...] 在指令中表示为一个内存单元,比如 [0] 中0则表示该内存单元的偏移地址,而该内存单元对应的段地址,则在DS中存放。CPU在执行该条指令时,会自动去取出DS中的数据当作内存单元的段地址来使用。

mov al,[0] 实际上是一个简略写法,为了加强理解,你完全可以写成 mov al,ds:[0],这样的看起来是不是清晰了很多呢。

使用Debug来执行

?我们此前学习了Debug工具的使用,还记得如何向内存写入汇编指令么?当然是A命令。那么下面就让我们使用Debug,来亲自执行并观察上述三条汇编指令执行结果。

打开Debug,使用A命令,向内存地址 2000:0 位置写入上述三条汇编指令

写入内存完成后,我们还需要一步,就是把CS:IP指向汇编指令所在的内存地址,这样CPU才会执行,使用R命令,修改CS、IP这两个寄存器的值:

?再使用R命令查看一下是否修改成功:

确实修改完成,我们能当到当前CS:IP 执行的汇编语句正是上述语句的第一条:mov bx,1000H?

这里可能会有一些疑问的地方,我们上述的汇编语句中,数字后面都是带有字母“H”,而Debug中,却没有字母“H”,1000H变成了1000,这是什么意思?

这其实也是一个易混淆点:

我们之前说到数字后面加一个字母“H”,表示这个数字是十六进制,例如1000H,则表示这个1000是十六进制下的1000,十进制表示为 4096。而在Debug中,显示的数据默认全部都是十六进制,不存在其他进制,所以就不需要增加字母“H”作以标明,在Debug中显示1000,就是表明这是十六进制1000。

解决了疑惑,那么接下来就让我们开始执行汇编语句,使用T命令进行单步执行:

?单步执行 mov bx,1000H后,我们可以看到BX 寄存器的值由之前的0变成了1000H,再执行一次T命令:

?单步执行 mov ds,bx后,我们可以看到DS段寄存的值由之前的073FH变成了1000H。这个时候我们注意到,图片右下角的 DS:0000=00?,这个展示的是DS:0地址单元下的内容为0,我们观察到此时AX寄存器也为0,那么执行 mov al,[0],AL值还是不变的。

为了看到变化,我们这里修改下内存地址1000H:0单元的内容,使用E命令,将内容改为1;修改完成后使用D命令查看修改结果:

?地址1000H:0单元内容被修改为1,那么我们就可以执行最后一条汇编指令,使用T命令:

执行完成后,我们观察到AL值为1。至此我们完成了内存访问的全过程。

向内存中写入数据

在上面的讲述中,我们完成了从内存中读取数据的操作,那么如何向内存中写数据呢?

其实很简单,我们只需要把指令:mov al,[0],修改为:mov [0],al 即可。

MOV 指令就是拿右边的数据覆盖左边的数据,操作对象可以是寄存器也可以是内存单元,所以指令?mov [0],al?,意思就是将AL寄存器中的值放入内存地址DS:[0]单元中。

我们还是使用Debug来实际操作一下,使用A命令写入以下汇编指令:

mov bx,1000H
mov ds,bx
mov al,afH
mov [0],al

在上述汇编语句中,我们设置DS完毕后,设置AL寄存器值为 AFH,然后指令设置DS:[0]值为AL寄存器值。

使用T命令进行单步执行:

?接下来就是用D命令来查看1000H:0单元内容是否被修改:

?确实已经被修改为AFH,证明我们汇编指令执行成功。

本篇结束语

在本篇的学习中,我们学习了DS段寄存器的意义和它的使用,还有如何向内存中读写字节数据。理解了格式:[...]的含义和它与DS段寄存器之间的联系。

在下篇博文中,我们将学习和探讨如何使用DS段寄存器访问内存中的字数据。

感谢围观,转发分享请标明出处,谢谢!

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-02-09 20:51:47  更:2022-02-09 20:52:08 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 10:18:28-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码