第五章 [BX]和loop指令
5.1 [bx]
[bx]是什么
和 [0] 有些类似,[0] 表示内存单元,它的偏移地址是 0。
例如:
mov ax, [0]
内存以字节为单位;ax以字(16bit = 2Byte)为单位;al以字节为单位。所以,mov ax, [0]
解读为把偏移地址为 0 的内存单元处的一个字对应的内容复制到 ax 寄存器中。mov al, [0]
解读为把偏移地址为 0 的内存单元处的一个字节对应的内容复制到 ax 寄存器中,因为 al 寄存器的长度为一个字节。
[bx]和内存单元的描述
我们要完整地描述一个内存单元,需要两个信息:
内存单元的地址;
内存单元的的长度(类型)。
我们用[0]表示一个内存单元时,0表示单元的偏移地址,段地址默认在ds中,单元的长度(类型)可以由具体指令中的其它操作对象(比如说寄存器)指出,如前边的 ax、al。若是ax,则以字单位传输;al,则以字节单位传输。
针对在MASM中的情况,[bx]同样也表示一个内存单元,它的偏移地址在bx中,比如下面的指令:
mov ax, [bx]
在MASM情况下,要实现“把偏移地址为 0 对应的内存单元的内容传给 ax 寄存器”,只能这么写:
mov bx, 0 mov ax, [bx]
题外话
在MASM中,例如下面一段汇编代码:
xxx.asm 文件内容为:
assume cs:codesgcodesg segmentfishcc:mov ax, 2000Hmov ds, axmov al, [0]mov bl, [1]mov cl, [2]mov dl, [3]mov ax, 4C00Hint 21Hcodesg endsend fishcc
注:在 MASM 下折腾汇编语言时,代码
mov bl, [1]
不能解读为把偏移地址为 1 处的内存单元的内容复制到 bl 寄存器,而应该解读为把 1 赋值给 bl 寄存器。在 Debug 中我们若用
-a
输入汇编指令mov bl, [1]
则按正常解读。解读为把偏移地址为 1 处的内存单元的内容复制到 bl 寄存器。
也就是说,当在以后缀为 .asm 文件内写入汇编指令时,才特殊对待。其它情况按汇编语法解释理解即可。
5.2 Loop指令
英文单词“loop”有循环的含义,显然这个指令和循环有关。
描述性符号 “()”
为了描述上的简洁,在以后的课程中,我们将使用一个描述性的符号 “()” 来表示一个寄存器或一个内存单元中的内容。也就是说括号的作用是取内容。比如:
ax 中的内容为 0010H,我们可以这样来描述:(ax) = 0010H
2000:1000 处的内容为 0010H,我们可以这样来描述:(21000) = 0010H
对于
mov ax,[2]
的功能,我们可以这样来描述:(ax) = ((ds) * 16 + 2)对于
mov [2],ax
的功能,我们可以这样来描述:((ds) * 16 + 2) = (ax)对于
add ax,2
的功能,我们可以这样来描述:(ax) = (ax) + 2对于
add ax,bx
的功能,我们可以这样来描述:(ax) = (ax) + (bx)对于
push ax
的功能,我们可以这样来描述(push,入栈,先修改栈顶指针然后存入数据;pull,出栈,先取出数据后修改栈顶指针。):(sp) = (sp) - 2
((ss) * 16 + (sp)) = (ax)
对于
pop ax
的功能,我们可以这样来描述:(ax) = ((ss) * 16 + (sp))
(sp) = (sp) + 2
约定符号 idata 表示常量
我们在 Debug 中写过类似的指令:mov ax,[0]
表示将 ds:0
处的数据送入 ax 中。指令中,在 “[...]” 里用一个常量 0 表示内存单元的偏移地址。以后,我们用 idata 表示常量。例如:
mov ax,[idata]
就代表mov ax,[1]
、mov ax,[2]
、mov ax,[3]
等。mov bx,idata
就代表mov bx,1
、mov bx,2
、mov bx,3
等。mov ds,idata
就代表mov ds,1
、mov ds,2
等,它们都是非法指令(因为段寄存器不能直接操作)。
5.1 [bx]
我们来看一看下面指令的功能:
mov ax,[bx]
功能:bx 中存放的数据作为一个偏移地址 EA,段地址 SA 默认在 ds 中,将 SA:EA 处的数据送入 ax 中。
即:(ax) = ((ds) * 16 + (bx))
mov [bx],ax
功能:bx 中存放的数据作为一个偏移地址 EA,段地址 SA 默认在 ds 中,将 ax 中的数据送入内存 SA:EA 处。
即:((ds) * 16 + (bx)) = (ax)
问题 5.1
准备工作:
我们首先在 masm 根目录下创建 test.asm 文件,并写入内容:
assume cs:codesgcodesg segmentfishcc: mov ax, 2000Hmov ds, axmov bx, 1000Hmov ax, [bx]inc bxinc bxmov [bx], axinc bxinc bxmov [bx], axinc bxmov [bx], alinc bxmov [bx], alcodesg endsend fishcc
然后 Debug 生成的 test.exe 这个程序,单步调试来看一看。以上过程如下图:
然后修改内存 2000:1000 处的内容为 be 00
查看是否修改成功:
问题 5.1 分析
先看一下程序的前三条指令:
mov ax, 2000H mov ds, ax mov bx, 1000H
这三条指令执行后:
ds = 2000H
bx = 1000H
附图:
再看第4条指令:
mov ax, [bx]
。执行前:ds = 2000H, bx = 1000H,则mov ax, [bx]
将把内存 2000:1000 处的字型数据送入 ax 中。该指令执行后,ax = 00beH。附图:
再看5、6条指令:
inc bx inc bx
指令执行前:bx = 1000H
执行后:bx = 1002H
附图:
再看第7条指令:
mov [bx], ax
指令执行前:ds = 2000H, bx = 1002H,则
mov [bx], ax
将把 ax 中的数据送入内存 2000:1002 处。指令执行后:2000:1002 单元的内容为 BE,2000:1003 单元的内容为 00。
附图:
接下来,第8、9条指令:
inc bx inc bx
这两条指令执行前 bx = 1002H,执行后 bx = 1004H。
附图:
接下来,第10条指令:
mov [bx], ax
指令执行前:ds = 2000H,bx = 1004H,则
mov [bx], ax
将把 ax 中的数据送入内存 2000:1004 处。指令执行后,2000:1004 单元的内容为 BE,2000:1005 单元的内容为 00。
接下来,第11条指令:
inc bx
。这条指令执行前 bx = 1004H,执行后 bx = 1005H。附图:
接下来,第12条指令:
mov [bx], al
指令执行前:ds = 2000H,bx = 1005H,则
mov [bx], al
将把 al 中的数据送入内存 2000:1005 处。指令执行后,2000:1005 单元的内容为 BE。附图:
接下来,第13条指令:
inc bx
。这条指令执行前 bx = 1005H,执行后 bx = 1006H。附图:
接下来,第14条指令:
mov [bx], al
指令执行前:ds = 2000H,bx = 1006H,则 mov [bx], al
将把 al 中的数据送入内存 2000:1006 处。指令执行后,2000:1006 单元的内容为 BE。
附图:
### Loop 指令
- 格式:loop 标号
- CPU执行loop指令的时候,要进行两步操作:
- (cx) = (cx) - 1;
- 判断 cx 中的值,不为零则转至标号处执行程序,如果为零则向下执行。
- 从上面的描述中,我们可以看到,cx 中的值影响着loop指令的执行结果。通常(注意,我们说的是通常情况)我们用loop指令来实现循环功能,cx 中存放循环次数。下面我们结合一个例子来具体看一看loop指令执行流程。
### 程序 5.1
在MASM环境的根目录下创建待编译文件loop.asm,在其中写入内容:
assume cs:code
code segmentaddrs:mov ax,2mov cx,11s:add ax, axloop smov ax,4c00hint 21hcode ends
end addrs
注意:微软的MASM默认是十进制的,所以指令 mov ax,4c00h
中的 4c00
要加上 h/H
。Debug默认是十六进制的,所以我们在debug中则用加 h/H
。
然后 Debug 生成的 loop.exe 这个程序,单步调试来看一看。以上过程如下图:
首先我们把ax寄存器的值赋值为2,cx原本默认是存储这个程序的大小,在这里表面程序的大小为000FH,即15个字节。
附图:
然后指令 mov cx,000b
将 11 赋值给 cx 寄存器。
附图:
观察 cx 寄存器的值,直到 cx 减为 0。此时循环结束,ax 寄存器的值为 1000H,转换成十进制正好是 4096 = \(2^{12}\) 。
附图:
然后用debug的 t 命令继续执行循环后边的语句 mov ax,4c00h
。int 21
表示程序结束,键入debug的 p 命令结束程序;接着键入debug的q命令退出Debug。键入 exit 退出终端。
附图:
小结
从上边的课程中,我们可以总结出用 cx 和 loop 指令相配合实现循环功能的三个要点:
- 在 cx 中存放循环次数;
- loop指令中的标号所标识地址要在前面;
- 循环执行的程序段,要写在标号和loop指令的中间。
用 cx 和 loop 指令相配合实现循环功能的程序框架如下:
mov cx,循环次数
s:
循环执行的程序段
loop s
指令 loop s
会做三件事:
- (cx) = (cx) - 1;
- 判断 cx 中的值,不为零则转至标号(s)处执行程序;
- 如果为零则向下执行。
温故而知新
- [bx] 的作用:作为偏移地址与DS配合
- loop 和 cx 合作
- debug 的 -g 偏移地址命令和 -p 命令
5.3 在Debug中跟踪用loop指令实现的循环程序
5.4 Debug和汇编编译器Masm对指令的不同处理
正是由于它俩对汇编语法的不同处理,诞生了 [bx] 的应用。
我们在Debug中写过类似的指令:
mov ax,[0]
表示将 ds:0 处的数据送入 al 中。因为内存单元是一个字节,ax 是两个字节。所以,该语句使 al 内容为 ds:0 处的数据;ah 默认置为 0。
但是在汇编元程序中(即:Masm),指令“mov ax,[0]”被编译器当作指令“mov ax,0”处理。
示例:
将内存2000:0、2000:1、2000:2、2000:3单元中的数据送入al、bl、cl、dl中。
- 在Debug中编程实现
- 汇编程序实现
两种实现的实际实施情况
在Debug中编程实现
回车
debug的 -r 命令:查看当前寄存器的值;
debug的 -t 命令:向前执行一条指令;
debug的 -d 命令:查看内存单元内容(比如查看内存从地址1000:0处开始,8个字节的内容);
debug的 -e 命令:修改内存单元内容(比如修改内存地址1000:0单元的内容);
debug的 -u 命令:将内存中的机器码翻译为汇编代码;
debug的 -a 命令:以汇编语言的形式在内存中写入一段程序。
我们现在用 -r 命令查看当前 ds 寄存器内容(即当前地址),在此处写入一段汇编代码:
接着设置 CS:IP 的值为 0b2a:0000 ,CS 的值已经是 0b2a,只要把 IP 指向 0000 即可。
附图:
注:在debug中默认的单位是十六进制;在Masm中默认的单位是十进制。
接着就可以用debug的 -t 命令单步跟踪观察刚刚输入的汇编代码对寄存器操作的情况了。
附图:
对比汇编程序实现
在Masm环境的根目录创建测试文件 test.asm ,写入下面代码:
assume cs:code
code segmentmov ax,2000hmov ds,axmov al,[0]mov bl,[1]mov cl,[2]mov dl,[3]mov ax,4c00hint 21h
code ends
end
注意:
- Masm只认十进制,所以第二行的 h/H 不要忘记写。
- 还有就是 Masm 不认中括号,类似于
mov al,[0]
这样的命令,实现的效果是把 0 赋值给 al 寄存器,而不是把内存偏移地址 0 处的内容复制到 al 寄存器。mov al,[0]
和mov al,0
在 Masm 是等价的。
附图:
注:如上边注意中提到一样。我们在 test.asm 中写的汇编命令是 mov al,[0]
,Masm 只会把 0 赋值给 al 寄存器。
mov bl,[1]
mov cl,[2]
mov dl,[3]
也是一样的道理:
若我们想把内存偏移地址 0 处的内容复制到 al 寄存器,怎么实现呢?这时候需要借助 bx 寄存器。
修改上边 test.asm 中的汇编代码如下:
assume cs:code
code segmentmov ax,2000hmov ds,axmov bx,0mov al,[bx]mov bx,1mov bl,[bx]mov bx,2mov cl,[bx]mov bx,3mov dl,[bx]mov ax,4c00hint 21h
code ends
end
重新编译 test.asm
,调试 test.exe
。即可实现我们想要的把内存偏移地址 0 处的内容复制到 al 寄存器。因为内存地址 2000:0000 单元的内容此例正好为0,我们不好看出效果。我们直接看把内存偏移地址 1 处的内容复制到 bl 寄存器的情况。
附图:
注:内存单元 2000:0 和 2000:1 的内容都为0。
如果一定要像DEBUG那样
在MASM中 mov ax,[2]
是解释为 mov ax,2
的。一般我们是通过 bx 来代替,像前边我们先 mov bx,2
再通过 mov ax,[bx]
来实现。但是我们要像DEBUG一样直接用 [2]
可以吗?答案是可以的,不过要加上段地址。
assume cs:code
code segmentmov ax,2000hmov ds,axmov al,ds:[0]mov bl,ds:[1]mov cl,ds:[2]mov dl,ds:[3]mov ax,4c00hint 21h
code ends
end
5.5 loop和[bx]的联合应用
5.6 段前缀
- 指令
mov ax,[bx]
中,内存单元的偏移地址由 bx 给出,而段地址默认在 ds 中。
5.7 一段安全的空间
在一般的PC机中,DOS方式下(实模式下),DOS和其他合法的程序一般都不会使用 0:200~0:2FF (0:200h~0:2FFh) 的256个字节的空间。所以,我们使用这段空间是安全的。
5.8 段前缀的使用
转载于:https://www.cnblogs.com/houhaibushihai/p/9664630.html
第五章 [BX]和loop指令相关推荐
- 《汇编语言》第5章 [BX]和loop指令
1.[bx]和内存单元的描述 [bx]是什么呢?和[0]有些类似,[0]表示内存单元,它的偏移地址是0.比如在下面的指令中(在debug中使用): mov ax,[0] 将一个内存单元的内容送入ax, ...
- 《汇编语言》第5章 [BX]和loop指令——实验4[bx]和loop的使用
本篇是第5章的实验--[bx]和loop的使用 (1)编程,向内存0:200~0:23F依次传送数据0~63(3FH). 解答: assume cs:codesg codesg segmentmov ...
- [BX]和loop指令03 - 零基础入门学习汇编语言25
第五章:[BX]和loop指令03 让编程改变世界 Change the world by program 从上边的课程中,我们可以总结出用cx和loop 指令相配合实现循环功能的三个要点: (1)在 ...
- [BX] 和 loop 指令---汇编学习笔记
[BX] 和 loop 指令 [bx]和内存单元的描述 loop 我们定义的描述性的符号:"()","()"中的元素可以有3中类型:寄存器名.段寄存器名.内存单 ...
- [bx]和loop指令编程
[bx]和loop指令编程 一. 实验目的 二.实验内容 三. 实验步骤 四. 结果 五. 心得体会 六. 实验与思考 一. 实验目的 1.掌握[bx]和loop指令的用法. 2.结合已学知识灵活应用 ...
- [bx]与loop指令
[bx]与loop指令 文章目录 [bx]与loop指令 1.[bx]与loop指令概念 2.[bx]和loop的联合应用 3.段前缀概念 4.包含多个段的程序案例 1.[bx]与loop指令概念 [ ...
- 汇编语言知识点总结之五:第五章《[bx]和loop指令》
1.[bx]和内存单元的描述 [0]表示内存单元,它的偏移地址是0.比如在Debug中使用,如下指令: mov ax, [0] 代表:将一个内存单元的内容送入ax,这个内存单元的长度为2字节(字单元) ...
- 汇编(六):[BX] 和 Loop 指令
文章目录 [bx] Loop指令 Debug 和汇编编译器 Masm 对指令的不同处理 loop 和 [bx] 的联合应用 段前缀 一段安全的空间 段前缀的使用 [bx] 1.[bx]是什么呢? 和[ ...
- [汇编语言][bx]和loop指令
目录 一.[bx]与loop基本描述 二.[BX] 三.Loop指令 四.在Debug中跟踪用loop指令实现的循环程序 五.Debug和汇编编译器masm对指令的不同处理 六.loop和[bx]的联 ...
最新文章
- linux 集群配置ssh无密码访问
- 清华大学「天机」芯片登上Nature封面:类脑加传统计算融合实现通用人工智能...
- pmp每日三题(2022年3月14日)
- 自动化测试遇到的难点_自动化测试过程中遇到的问题主要有什么?
- oracle仲裁磁盘是一块磁盘吗,基于ASM冗余设计的架构,仲裁磁盘组应该如何去规划?...
- python 整数最大_Python程序使用floor()方法查找最大整数
- codeforces 816 B. Karen and Coffee(思维)
- click Commands and Groups
- 水泵怎么做_燃气壁挂炉初次调试,要怎么做才好?
- 中小企业电子商务如何发展?
- php 去除 ufeff,PHP去掉诡异的BOM \ufeff
- 改变Ubuntu18.04初始键盘布局
- 快速在服务器上搭建Halo个人博客
- 快速搭建简单图床 - 远程访问本地搭建的EasyImage图床【内网穿透】
- matlab 差分方程的解(解答qq网友)
- 光猫桥接后宽带降速问题解决
- 电脑预装linux系统,电脑预装Linux第三方系统怎么破?看外行人重装Win10系统的精准攻略...
- USB 协议 (五) 枚举
- 【数字化】“网络效应”指南:13 种网络效应全解析,带你了解巨头成功的秘密
- ES6新特性----面试
热门文章
- SMETA验厂辅导,贸易公司、物流仓储公司是否可以申请SMETA审核
- IBuySpy 网上商店的设计和实现
- 双核处理器的双核是什么意思?
- Google Earth Engine(GEE)——全球洪水数据库 v1 (2000-2018年)
- 【UCIe】UCIe DLP/DLLP 介绍
- Pandas的MultiIndex多层索引使用
- cad标注文字避让lisp_请教大家如何将标注标准设定“文字位置设置为置中”
- Jupyter中的魔法函数
- pack 和 unpack
- 秀一下大连TimesTen 18.1培训的结业证