引言

在上篇博文中,我们已经熟悉了解如何编译、连接并运行一个程序,对MSAM工具和LINK工具的使用也已经掌握。那么从本片博文开始,也就意味着工具类的学习告此段落,下面将会是汇编语言开发方面的讲述。

本篇博文的学习目标:

1、学习 [bx] 格式的意义

2、区分Debug与MASM编译器对指令的不同处理

3、编码感受 [bx] 的用法

目标一定,就让我们赶快开始本篇的学习吧!

BX寄存器

我们知道8086CPU中有四个通用寄存器:AX、BX、CX、DX。

在之前的学习中我们一直接触的都是AX,比如使用AX对段寄存器赋值。那么接下来,我们将逐渐接触到BX、CX、DX他们三个的其他特殊用途,现在我们先学习BX寄存器的特殊用法。

[BX]的意义

对于[...]格式,实际上我们并不是很陌生,在前几篇<访问内存>系列的博文中,我们知道使用DS:[idata]的形式来访问内存,idata这里表示为一个立即数(常量),对应的是相对于DS数据段的偏移。比如 mov ax,[0],意思为将内存地址为ds:0下的字单元数据送入AX寄存器内。

那么,[bx]实际上和[idata]是相同的作用,都是和DS配合进行内存的访问

比如:

mov ax,[bx]

意思为:将内存地址ds:bx下的字单元数据送入AX寄存器中。此时,BX寄存器中的内容就是相对于DS数据段的偏移。

假如此时BX寄存器内容为0,那么 mov ax,[bx] 就等同于 mov ax,[0];BX寄存器内容为1,那么 mov ax,[bx] 就等同于 mov ax,[1]。

你可能会好奇,为什么会存在[bx]?不是已经有了[idata]了么!

之所以要有[bx],是为了方便在程序中便捷的寻址。idata就是一个常量数字,一旦写进代码它就是固定的数字,那么在运行中就无法做到动态寻址,除非你修改代码,否则一直寻的都是一处固定的内存单元地址。

BX寄存器的值则是可以随时改变的,也就意味着 [bx] 的形式可以做到一个动态寻址,而不是像 [idata]这样写死的无法改变。这样,我们通过在代码中动态修改BX寄存器的值,就可以达到随心所欲的动态寻址

Debug与MASM的区别

Debug工具和Masm工具它们两个都是DOS系统下的程序,Debug工具是调式程序,可以直观的感受程序每一步执行给寄存器或者内存空间带来的变化,Masm工具是编译程序,可以将源程序文件编译成中间文件。

很显然,它们两个在功能上就有很大的区别。不过本篇博文中我们主要讲述的是 [bx],所以当然要谈谈针对 [...]的格式,它们两个之间的区别。

Debug中的 [...]

还记得如何在Debug下通过 [...]形式来访问内存吗?现在我们就来复习一下:

Debug下,我们使用A命令以汇编指令的形式向内存中写入机器码

以 [idata] 的形式来进行内存访问

例如:mov ax,[0]

这里我们准备一份代码:

mov ax,2000H
mov ds,ax
mov ax,[0]

很简单,将内存地址 2000H:0H下的字单元数据送入AX寄存器中。我们先使用A命令将这三条汇编指令写入内存:

然后我们使用U命令,查看一下内存中指令语句的形式:

基本和我们使用A命令输入的语句保持一致,那么下面,我们使用 [bx] 的形式来再看一下,使用A命令将下面几条汇编指令写入内存:

mov ax,2000H
mov ds,ax
mov bx,1
mov ax,[bx]

然后使用U命令,查看内存中的汇编语句形式:

还是基本和A命令写入的格式保持了一致,并未变化。

下面,我们就使用T命令来执行一下:

我们可以看到 [bx] ,bx寄存器值为1,ds:[bx]能够准确访问到了内存地址 2000H:1H下的字段元数据,等效于 [1]的形式。

那么我们就能得出结论,Debug中 [idata] 和 [bx] 这两种形式并无差别,起到的作用都是等效的

Masm中的 [...]

看完了Debug,那么我们来看看Masm工具会对这两种形式有何不同的解释呢?

Masm是编译器,所以这次我们需要在Nodepad++中写代码了。还是上面的汇编语句,首先我们先看 [idata]的表现。新建文件 s2.asm,并在NodePadd++中打开:

这里要注意提醒的是:

  1. s2.asm文件要和Masm工具在同一目录下
  2. 源程序中一定要定义CS代码段
  3. 不要忘记写上程序结束返回

写完源程序后保存一下,就可以使用Masm工具和Link工具生成可执行文件:

下面就来使用Debug加载一下可执行程序文件:

进入Debug后,我们先不急着执行,我们先使用U命令来查看一下,加载进内存中的汇编指令是什么样子呢?会不会和源程序中的汇编指令保持一致呢?

哦豁!注意看画红线的部分,我们记得这条语句原本的样子是:mov ax,[0],结果加载进内存中怎么是:mov ax,0?这是怎么回事呢?

究其原因,却是Masm编译器的问题。

Masm工具是无法识别源程序中 [idata] 的格式,碰到 [idata] 的格式便会把它当作常量来对待。[idata] 在Masm工具看来,就是常量 idata。所以我们源程序中的mov ax,[0],编译之后便变成了mov ax,idata。

那么现在,我们换上第二份代码,来看看Masm编译器是如何看待 [bx]的格式。我们修改代码如下:

我们将s2.asm源程序文件编译连接,然后将可执行程序使用Debug加载进内存中,使用U命令来查看此时内存中的汇编指令:

OK,这次我们发现是正常的mov ax,[bx],说明Masm编译器是可以正确识别并编译 [bx]的格式。

小结

那么现在,我们可以对Debug和Masm的区别做一个总结:

在Debug工具中,可以准确识别 [idata] 和 [bx] 两种不同的格式;

在Masm编译器中,则会将 [idata] 的格式看做常量 idata,例如 mov ax,[idata],编译后则是 mov ax,idata。对于 [bx] 的格式,则会做到准确识别。

我们已经明白了两者的不同,那么我们再来进行深入探究:任何情况下,Masm编译器都会将 [idata] 的格式看做常量 idata 吗?

光靠脑袋猜想是不行的,我们需要亲自动手去验证。已知,mov ax,[idata] ,会被编译成 mov ax,idata,那么我们写成 mov ax,ds:[idata],编译结果还会一样吗?

话不多说,我们先动手验证。修改我们的代码如下:

注意看,这里我们将 mov ax,[0] 语句修改为了 mov ax,ds:[0]。

我们将s2.asm源程序文件编译连接后,使用Debug将生成的可执行程序加载进内存中,使用命令U查看内存中的汇编指令:

哦豁,居然准确识别出来了,没有变成 mov ax,0,而是正确的语句:mov ax,[0]。

这是为什么呢?不是说Masm编译器会将 [idata] 看成常量 idata吗,只不过加了一个 ds:,结果为什么就会变了呢?

现在,我们可以揭秘了。首先我们需要明白这两种不同的写法:

1、mov ax,[idata]

2、mov ax,ds:[idata]

首先我们知道,这两种形式所阐述的意思,即所实现的功能都是相同的:将内存地址 ds:0下的字单元内容送入AX寄存器中。mov ax,[idata],实际上是 mov ax,ds:[idata] 的简略写法,CPU会默认数据段的段地址在DS寄存器中,然后使用DS寄存器中的数据和给定的偏移进行寻址。

既然两种形式表达意思一样,那么为什么还会出现不同的编译结果呢?

答案很明显,那就是Masm编译器显然不是和我们保持相同的想法和认同。在Masm看来,mov ax,[idata] 是一种弱指定,什么是弱指定?即:源程序中给出的 [idata] 可能不是数据段下的偏移地址,它还可能是代码段CS下的偏移,也可以是栈段SS下的偏移,亦或者是补充段ES下的偏移!

Masm它只是个工具,说白了就是一段程序,它当然是没办法理解人类的想法。而且它还要保证编译后的程序准确度和完整度,碰到这种不知所以的弱指定 [idata],肯定不敢贸然就认为这就是某个段的偏移地址,既然无法确定,那就干脆认为哪个段的偏移地址都不是,所以就把 [idata] 当作常量来处理啦!

mov ax,ds:[0] 则不一样,这是强指定,什么是强指定?即:在源程序中明确的告诉编译器,我给出的 [idata] 它就是某个段下的偏移地址

强指定的格式即为:xx:[idata],这里 ds:[0] 意思为:明确告诉编译器,[0] 是数据段DS下的偏移地址。正因如此,Masm编译器知道这就是数据段下的偏移,所以便会正确进行编译,编译结果正常。

经过上述的探讨,博主这里给出建议:

在编写源程序中,请尽量使用强指定的格式,1:可以避免编译结果出错的问题,2:增强了源程序的可读性。

本篇结束语

在本篇博文中,我们主要讲述了 [bx] 格式访问内存,Debug工具和Masm工具对于 [bx] 不同的解释。此外,我们明白了为什么Masm会对 [idata] 有不同的解释,取决于弱指定和强指定。

那么在下篇博文中,我们将接触到汇编中的循环,学习CX寄存器在其中承担的角色。

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

汇编学习教程:bx的作用相关推荐

  1. 汇编学习教程:走进 bp

    引言 此前我们学习了 bp 寄存器,我们知道 bp 的作用是为访问栈空间数据提供方便,其默认绑定的段寄存器就是 SS 段寄存器.在此前的博文中博主提及到,bp 的作用其实不止方便访问栈空间数据这一条, ...

  2. 汇编学习教程:灵活寻址(三)

    引言: 在上篇博文中,我们学习了一个灵活寻址方式:[bx+idata],该方式我们可以形象的将它类比成高级语言中的一维数组,其中idata可以看成是数组的起始地址,bx看成是数组的下标. 除此之外,我 ...

  3. 汇编学习教程:灵活寻址(二)

    引言 在上篇博文中,我们主要学习了两个指令and和or,它们两个目前最主要的功能就是对英文字母进行大小写转换.学习这两个指令主要是为接下来的学习做铺垫,因为接下来的编程案例中需要使用到. 那么从本片开 ...

  4. 汇编学习教程:灵活寻址(四)

    引言 在上篇博文中,我们学习了 [bx+si] 的灵活寻址形式,由此讲解了汇编中的多重循环实现.那么本篇博文中,我们将继续学习灵活寻址其他实现形式. 本次学习从一道编程案例开始学起. 编程示例如下: ...

  5. 汇编学习教程:循环和CX寄存器

    引言 在上面博文中,我们主要学习了BX寄存器配合DS寄存器完成内存访问,同时也探究了Masm编译器面对弱指定和强指定两种情况时所产生的不同编译结果. 我们提到:xx:[idata] 是强指定格式,这种 ...

  6. 8086汇编学习之[BX],CX寄存器与loop指令,ES寄存器等

    同类学习笔记总结: (一).8086汇编学习之基础知识.通用寄存器.CS/IP寄存器与Debug的使用 (二).8086汇编学习之DS寄存器.SS/SP寄存器 一.汇编程序的基本格式: 1.基本格式与 ...

  7. 汇编学习教程:开发第一步

    引言 此前我们详细讲述了有关内存访问.CPU相关知识.寄存器相关等等,而这些的目的最终都是为了实战开发而准备的.从本片博文开始,我们将正式进入开发相关的学习,相信大家已经急不可耐了,准备一腔热血写代码 ...

  8. 汇编学习教程:编译、连接、运行

    引言 在上篇博文中,我们详细学习了汇编源程序的组成,并且下载好两个必须的工具:编译源程序的工具 MASM.exe和处理中间文件的工具 LINK.exe. 我们在上篇博文中只是大致了解了一下MASM.e ...

  9. 汇编学习教程:CPU内的小秘密

    引言 在上一篇博文中,我们主要讲述了CPU大致的工作原理,以及CPU的小伙伴存储器,CPU与其他电子器件的交互逻辑等,那么本篇博文将由外及内,回过头来说说CPU内的一些知识点.那么就让我们赶紧开始本次 ...

最新文章

  1. [转] C# 获取程序运行目录
  2. 前端代码标准最佳实践:javascript篇
  3. 指南 | Pytorch定义网络的几种方法
  4. 单结晶体管的导电特性_适用于印刷电子的导电墨水可在纸和PET薄膜上印刷薄膜晶体管...
  5. ASCLL编码详解,ASCLL编码对照表
  6. 如何使用视频转换器将ogg格式转换为MP3格式
  7. iis7.5 php 404.17,部署IISHTTP 404.17无法由静态文件处理程序来处理
  8. 他一篇论文未发博士毕业!中科院最年轻院士入职浙大!
  9. 计算机手机共享上网,上网教程_电脑wifi怎么实现手机共享上网 - 驱动管家
  10. 黄杏元《地理信息系统概论》考研复习考点精讲(三)
  11. Hyper-v 虚拟机固定Ip、连接外网
  12. golang dep安装
  13. .net core 下文件压缩打包下载
  14. FPGA数字信号处理基础----使用HLS生成信号
  15. DNSPod x ikuai 联合打造,DNS防御业务正式上线!
  16. 深度学习驱动智能搜索引擎,RankBrain革了SEO的命
  17. 数据恢复 diskginus
  18. 牛津英语字典pdf下载_牛津树1阶段精讲笔记分享
  19. Codeforces118D Caesar's Legions(DP)
  20. jpa 托管_jpa深入

热门文章

  1. 组图:1896年雅典奥运会
  2. 【类不类三】来自星星的哥顿人与正则表达式
  3. python三个数从小到大排序
  4. 卡尔曼滤波原理及实现
  5. 成像锐利是什么意思_照片变得“锐利”是什么意思?
  6. 机械制造作业考研题目答案分享——工艺规程的制定
  7. Linux 之systemd服务简介
  8. 微信小程序 web-view 在ios显示空白页面
  9. html2canvas在ios中空白或者截图不完整解决。
  10. WPF,Silverlight与XAML读书笔记第三十七 - 可视化效果之Brush