汇编学习教程:访问内存(2)

本文详细介绍了8086CPU如何对内存进行字数据的操作,通过实例展示了MOV指令在读写字数据时的工作原理。通过Debug工具验证了MOV指令的不同形式,如MOV寄存器,内存单元和MOV内存单元,寄存器,并探讨了其对段寄存器的特殊限制,尤其是CS寄存器的不可修改性。同时,文章指出MOV指令可以将段寄存器的值写入内存,但不能从内存读取到CS寄存器。最后,总结了MOV指令对段寄存器操作的规则。
摘要由CSDN通过智能技术生成

引言

在上篇博文中,我们学习了内存中字节数据的读写操作,我们知道8086CPU中寄存器是十六位,可以一次性操作一个字的数据,所以我们势必要学习下该如何对内存进行字数据的操作。

字的传送

回想我们上篇博文中如何传输一个字节,我们使用格式:[...]来表明内存单元,默认DS段寄存器中的数据为段地址,CPU在执行中取出DS中的数据加上 [...] 中指定的偏移地址得到目的地址,对最后的目的地址内存单元进行读写操作。

同样,如果操作为一个字的数据,在代码的书写上和操作一个字节的数据基本相同。例如,读取内存地址字单元 1000H:0 的数据到AX寄存器中,代码:

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

还是需要使用格式 [...] 来指明偏移地址,区别就是AL寄存器,变成了AX寄存器。

知识点

只是改变了寄存器,就完成一个字的数据读取了?

MOV 指令中其实是有数据长度的,数据长度就是数据是字节还是字,后面还会学习到双字。我们在之前的讲述中有说过,现在复习一下:MOV指令什么时候传送的是一个字节数据,什么时候传送的是一个字数据,取决于它两个操作对象的数据大小

例如 mov al,[0],AL寄存器是八位,那么它对应的数据长度就是一个字节,所以CPU就会默认 MOV 一次传送的数据长度为一个字节;mov ax,[0],AX寄存器是十六位,那么它对应的数据长度就是一个字,所以CPU就会默认 MOV 一次传输的数据长度为一个字。

Debug实操验证

为了证实我们上述的说法,我们还是在Debug上进行实际操作一下,使用A命令将上述汇编指令写入内存地址 2000H:0 单元下:

接着使用R命令修改CS:IP为我们的汇编指令所在地址:

为了方便我们观察执行结果,我们将内存地址1000H:0下的字单元内容为:2E3CH:

 

 这里我们之前提过的混淆点已经出现了!一定要牢记规则“高位对应高位,低位对应低位”,所以1000H:0字节单元处,我们要放上十六进制数2E3CH的低位:3CH;1000H:1字节单元处,我们要放上十六进制数据2E3CH的高位:2EH。

下面我们就使用T命令来单步执行:

 观察执行完成后的AX寄存器值为2E3CH,说明读取字数据成功。

那么如何向内存中写入一个字的数据呢?

实际上和向内存中写入字节数据也基本一致,无非就是寄存器变成了十六位。以下代码实现将AX寄存器中的值写入内存地址1000H:0字单元:

mov bx,1000H
mov ds,bx
mov ax,4d2aH
mov [0],ax

小伙伴们请自行将上述代码在Debug中进行实操,这里博主就不进行演示了。

MOV指令的形式

现在我们能知道MOV指令有以下几种形式:

MOV 寄存器,自然数

MOV 寄存器,寄存器

MOV 寄存器,内存单元

MOV 内存单元,寄存器

MOV 段寄存器,寄存器

现在我们在对MOV指令的形式进行推断和探讨:

我们已知可以使用MOV指令通过通用寄存器来给段寄存器赋值,那么是不是说明通用寄存器和段寄存器之间有通路呢?所以我们 MOV 寄存器,段寄存器 应该可行性~ 

有猜想就需要去实际验证以下,我们在Debug中进行验证:

使用A命令向内存中写入下面一条汇编指令:

mov ax,cs

然后修改CS:IP,使用T命令进行单步执行,观察执行结果: 

 我们观察到,AX寄存器成功被修改为CS值,这就说明 MOV 寄存器,段寄存器 的形式是可行的!

我们继续探讨,已知 MOV 寄存器,内存单元 是可行的,段寄存器也是寄存器,那么可不可以 MOV 段寄存器,内存单元 呢?

还是在Debug中进行实际验证:

使用A命令向内存中写入下面一条汇编指令:

mov ds,[0]

 然后修改下DS:0字单元内容,修改CS:IP,最后使用T命令进行单步执行,观察实际结果:

 我们可以看到:DS寄存器的值确实被修改成了1000H:0字单元内容 073FH,说明 MOV 段寄存器,内存单元 是可行的。

既然我们确定了MOV 段寄存器,内存单元 可行,那么 MOV 内存单元,段寄存器 估计也是可行的,Debug 验证一下:

首先我们将DS修改回之前的值:1000H,然后使用A命令向内存中写入下面一条汇编指令:

mov [0],ds

修改CS:IP,使用T命令执行,执行后使用D命令查看内存单元内容,观察结果:

 发现1000H:0字单元确实被修改为1000H,说明 MOV 内存单元,段寄存器 也是可行的!

第一个拓展

在上面的实践中,我们验证了 MOV 段寄存器,内存单元 是可行的,那么真的对任何一个段寄存器都适用么?我们确定了DS段寄存器没问题,那么CS段寄存器是否也会遵循 MOV 段寄存器,内存单元 这种形式呢?

实际上 MOV 指令无法修改CS、IP内容,这在我们之前的博文中已经提到。还记得跳转指令:JMP么?这是CPU提供专门用来修改CS、IP的指令。有遗忘的小伙伴可以回头去翻看博文,在“好好搞懂段”博文中。

之前我们还没有学习Debug,所以并无法实际去做验证,而现在我们已经熟知了Debug的使用,所以在这里我们就来进行亲身体会:如果我们仍然使用MOV指令来修改CS,那么会发生什么呢?

我们这里先大胆假设,CS段寄存器同样适用 MOV 段寄存器,内存单元 ,抱着这样的想法,我们在Debug进行实际验证:

A命令向内存中写入下面一条汇编指令:

mov cs,[0]

修改下DS:[0]字单元内容,修改CS:IP,使用T命令执行,观察执行后的结果:

 

 我们首先修改DS:[0]字单元内容为 073FH,执行 mov cs,[0] 指令后,我们期望的结果是CS值被修改为073FH,但是我们却发现,CS值确实变了,但不是 073FH,而是 F000H;此外,IP的值也是异常的,本来应该是CH,结果变成了1060H。

很显然,我们并没有成功的修改CS值,也就是说 MOV 段寄存器,内存单元 这种形式并不适用CS段寄存器!

既然不适用,那我们换一种形式:MOV 段寄存器,寄存器 来再次尝试:

A命令向内存中写入下面汇编指令:

mov ax,073fH

mov cs,ax

修改CS:IP,使用T命令执行,观察结果:

 观察结果还是和 MOV 段寄存器,内存单元 一模一样!

这到底是为什么?为了弄清楚这个问题~首先我们先弄明白这个内存地址 F000H:1060H 

还记得我们之前的讲述吗?在讲“第一个实验”的那篇博文里,我们讲述了8086CPU中对内存地址空间的划分,忘记的同学可以回去再巩固一下~其中 C0000H~FFFFFH 这段内存空间为各类ROM地址空间,对外是只读的,无法修改。我们发现 F0000H:1060H 是位于这段内存空间中,也就是说 F000H:1060H 指向的数据根本就不是代码数据了,而是ROM信息。那么具体是什么信息?当然是程序崩溃信息啦~也就是说,CS:IP跳到了 F000H:1060H ,则说明程序发生了错误,此时CPU需要对外输入一些错误信息,来提示开发人员,程序发生了什么样的错误。

这就好像我们日常写的程序中出现了Bug,运行后日志展示一堆报错!日志报错,和这里是一样。

既然是程序出错了,那么怎么会没有出现错误信息啥的呢?这是因为Debug的原因,因为我们此时是使用T命令进行的单步执行(也就是调试),执行一条指令后会引发一个中断,CPU就不会继续执行下条指令,而是等待我们输入下条命令,所以我们看不到错误信息。

 好,我们现在明白了这个地址F000H:1060H所在的意义,那么好端端的,CS:IP 它两个值怎么会发生变化呢?是谁修改了CS:IP值呢?很显然,这并不是由我们修改的。

答案就是,这是操作系统所修改的。CPU在执行 mov cs,[0] 这条指令时,发生了一个内部中断,在中断过程中,CS:IP被修改为中断程序的地址入口,这样CPU便去执行了中断程序,F000H:1060H这个地址就是中断程序的入口地址。该中断程序是在操作系统启动时加到内地址空间内的,这部分的内容会在后面的讲述中说到,这里先不做详细解释。

为了增加认知,这个中断程序你可以把它想象成是我们开发中的try-catch 异常捕获,当程序执行中发生错误便会爆出一个异常,程序便转到catch,执行它那里处理异常的代码。

现在我们就可以给出最终结论:MOV 指令无法给CS、IP这两个寄存器赋值,这是CPU在被设计之初就已经被设定好的限制。如果你要是问为什么会有这种限制?那么我们只能猜测,可能是为了增加安全性,为了防止CS:IP被恶意篡改。毕竟CS:IP他们两个指向的是代码指令,重要性不言而喻!

第二个拓展

我们已经知道 MOV 指令无法修改CS值,那么可不可以反向操作呢?MOV 指令形式还有:MOV 内存单元,段寄存器 这种形式,所以我们可不可以将CS值写到内存单元中呢?

还是在Debug中进行验证:

A命令向内存中写入下面一条汇编指令:

mov [0],cs

修改CS:IP,使用T命令单步执行,执行完成后使用D命令查看内存单元内容:

 我们观察发现,DS:0处的字单元内容准确被修改为CS段寄存器值,并且执行后CS:IP值正常,这就说明 :MOV 内存单元,段寄存器 这种形式是适用CS寄存器的。对比之下我们可以得知,只要不是修改CS值,那它就没问题呀~

最终总结:

MOV 内存单元,段寄存器 这种形式适用于所有的段寄存器, MOV 段寄存器,内存单元 这种形式适用于除了CS段寄存器之外的所有段寄存器。这里很重要,请务必牢记!

本篇结束语

本篇博文中主要带大家一起探讨了CPU访问内存字单元的操作,讲解了MOV指令的各种形式,亲自执行并观察MOV操作CS寄存器后的结果,加深了我们的理解认知。

下篇博文中,我们将学习SS段寄存器相关的知识,理解SS段寄存器它的特性和作用。

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

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值