Java教程

[从零学习汇编语言] - 寄存器与内存访问

本文主要是介绍[从零学习汇编语言] - 寄存器与内存访问,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

文章目录

  • 前言
  • 一、 寄存器与数据
    • 1. 字节型数据与字型数据
    • 2. DS和[address]
  • 二、常用内存读写指令
    • 1. MOV指令
    • 2. add指令
    • 3. sub指令
  • 结语

前言

该系列博文基于王爽老师 <汇编语言 第四版> 一书,需要的同学链接自取:

链接:https://pan.baidu.com/s/1NAgD1Z15LtK1BuH92xmICA
提取码:xlzb

另外书中提到的DosBox软件不想去官网下载的小伙伴也可以自取:

链接:https://pan.baidu.com/s/1O6PnLb_hN-WUS2avicNpcw
提取码:xlzb

最后如果还没有计算机基础的同学,建议先补充下计算机相关的基础知识:

笔记目录总览

一、 寄存器与数据

1. 字节型数据与字型数据

这里我们要复习一下关于寄存器的一些基础知识,如果没有寄存器基础的同学建议先看下这篇博客:

[从零学习汇编语言] -寄存器详解

还记得在之前我们提到的四个十六位通用寄存器AX , BX, CX, DX 吗,当时我们做了个小实验证明了这四个十六位寄存器又分别是由高八位寄存器和第八位寄存器构成的。如果你忘了也不要紧,我们再来一遍这个实验:
第一步: 通过R指令查看寄存器内容
在这里插入图片描述
这里我们观察到此时AX寄存器对应的内存数据内容为十六位的0000
第二步 :通过R指令修改AX寄存器的值
在这里插入图片描述
我们通过R指令将AX寄存器中的值修改为了十六位的1111
第三步:分别修改AH和AL寄存器的值,观察AX寄存器的变化
在这里插入图片描述
在这里我们首先将AH寄存器的值更新为FF,再将AL寄存器的值修改为了00,然后我们观察此时AX寄存器的值,发现已经更新为了FF00,由此可证明AX寄存器是由AH寄存器AL寄存器构成。那么为什么设计师要将一个十六位寄存器拆分为两个八位寄存器呢?其实这是为了让寄存器可以更加灵活的适应不同长度的数据类型。还记得之前提到过的两种数据类型吗?

  1. 字节型数据: 字节型数据的单位为byte,1byte=8bit,即可以用来存放八位数据。
  2. 字型数据:字型数据的长度为2 byte,即可以用来存放十六位数据。

那么联想到我们之前提到过的AX寄存器是由两个八位寄存器构成,以此类推一个十六位的字型数据是由两个八位的字节型数据构成,两个字节型数据通过高八位和低八位的方式同时组成一个十六位数字。 为了验证我的猜想,我再进行一个实验:
第一步: 为指定内存地址输入指令观察数据组成
在这里插入图片描述
在这里我们可以观察到
在这里插入图片描述
在2000:0000地址处的01和02两个位置通过2211两个八位内存数据组合构成了我们输入的1122,这里细心的小伙伴可能观察到了一个现象:十六位数字1122中的22范围在内存中被放到了前面,这是为什么呢? 这里主要是由于字型数字在内存中的排序规则是高位数字+低位数字,这里的高位数字指的是相邻的内存中地址编号更大的一个。

2. DS和[address]

还记得之前我们介绍过的段寄存器吗?

ps: 如果忘记的小伙伴或者不清楚的小伙伴还是建议先复习下寄存器基础知识:
[从零学习汇编语言] - 寄存器详解

当CPU想要读写一个内存单元的时候,必须先给出这个内存单元的地址,在8086CPU中,内存地址是由段地址和偏移地址组成的,对应的我们的段寄存器主要就是用来存放段地址。
在这里插入图片描述
在四个段寄存器中,DS寄存器主要是负责存放要访问的数据段地址。比如我们想要读取1000H单元的内容,我们可以用如下方式进行:
在这里插入图片描述

这里给基础不太好的小伙伴解释下我们都做了什么

  1. 通过E指令修改从1000:0000开始的连续内存单元的数据
  2. 通过A指令录入想要执行的汇编指令
  3. MOV BX,1000 将BX寄存器的值修改为1000
  4. MOV DS,BX 将BX寄存器的值赋予DS段寄存器
  5. MOV AX,[0] 将地址值为DS:0的数据值赋予AX寄存器
  6. 通过T指令运行命令,观察内存变化

如果不清楚指令含义的同学,建议观看以下博文进行学习:
[从零学习汇编语言] - Debug指令与入门

细心的同学应该观察到了一个新的知识点: 在MOV AX,[0] 指令中包含了一个**[0]** 的概念,这其中的 [address] 的表达形式其实是表示了一个内存单元物理地址。而物理地址的表达方式为段地址×16+偏移地址,其中段地址就是存放在了DS段寄存器中,而偏移地址对应的就是 [address] 中的address。这时候我们再回过头看刚才运行的程序,是不是明白了些什么。

二、常用内存读写指令

1. MOV指令

之前我们在演示中频繁用到了MOV指令,但是一直没有详细的讲一下这个指令的含义,当时主要是考虑很多同学都是和博主一样从零基础学过来的,过早的接触汇编指令容易弄混,随着这么多天的学习下来,我相信同学们已经有足够的基础可以理解汇编指令了。
什么是MOV指令? mov指令是一种传送指令,其表示把一个字节,字或者双字的操作数从源位置传送到目标位置,具体可表示为: MOV 目标位置,源位置 的形式,源位置操作数不发生变化。
到目前为止,我们接触过的mov指令可以概括为如下格式:

在这里插入图片描述
当然,我们还要注意一些MOV指令特殊的地方:

  1. 目的操作数要与源操作数类型要一致,不能一个是字,一个是字节
  2. 目的操作数要和源操作数类型之一必须要有明确的类型
  3. 立即数不能作为目的操作数
  4. 不能用立即寻址方式给段寄存器传数
  5. 源操作数和目的操作数不能同时为存储器操作数,即存储单元之间不能用MOV指令直接传送
  6. CS和IP不能作为目的操作数,但CS可以作为源操作数。
  7. 段寄存器之间不能用MOV指令直接传送
  8. 在传送字单元时,遵循“高字节存放在高地址,低字节存放在低地址”的原则。

这里我们简单的试验下先为AX寄存器赋值,再将AX的值赋予BX:
在这里插入图片描述

2. add指令

什么是ADD指令? ADD的含义为两数相加(不包含进位)并将运算结果赋予目标寄存器。add指令支持的格式也与mov相近:
在这里插入图片描述
由于ADD指令MOV指令除了语义外基本相同,因此我们简单演示下ADD指令的效果:
将ax寄存器赋值1,将bx寄存器赋值2,计算ax+bx的值
在这里插入图片描述

3. sub指令

add指令相对的,sub指令是汇编中的减法运算,除语义外两者几乎没有区别,因此我们直接看效果:
将AX赋值2,BX赋值1,计算AX-BX
在这里插入图片描述

结语

今天我们介绍了通过段寄存器DS配合偏移地址的方式直接访问内存单元的方式,并且介绍了目前阶段使用频率最高的三个指令,希望小伙伴看完后最好将本篇示例跟着敲一敲,加深印象。
好了,今天的内容就到此结束了,有疑问的小伙伴欢迎评论区留言或者私信博主,博主会在第一时间为你解答。
码字不易,感到有收获的小伙伴记得要关注博主一键三连,不要当白嫖怪哦~
如果大家有什么意见和建议请评论区留言或私聊博主,博主会第一时间反馈的哦。

这篇关于[从零学习汇编语言] - 寄存器与内存访问的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!