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]和内存单元的描述

  • 我们要完整地描述一个内存单元,需要两个信息:

    1. 内存单元的地址;

    2. 内存单元的的长度(类型)。

    我们用[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,1mov bx,2mov bx,3 等。
  • mov ds,idata 就代表 mov ds,1mov 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 分析

  1. 先看一下程序的前三条指令:

    mov ax, 2000H
    mov ds, ax
    mov bx, 1000H

    这三条指令执行后:

    ds = 2000H

    bx = 1000H

    附图:

  2. 再看第4条指令:mov ax, [bx] 。执行前:ds = 2000H, bx = 1000H,则 mov ax, [bx] 将把内存 2000:1000 处的字型数据送入 ax 中。该指令执行后,ax = 00beH。

    附图:

  3. 再看5、6条指令:

    inc bx
    inc bx

    指令执行前:bx = 1000H

    执行后:bx = 1002H

    附图:

  4. 再看第7条指令:mov [bx], ax

    指令执行前:ds = 2000H, bx = 1002H,则 mov [bx], ax 将把 ax 中的数据送入内存 2000:1002 处。

    指令执行后:2000:1002 单元的内容为 BE,2000:1003 单元的内容为 00。

    附图:

  5. 接下来,第8、9条指令:

    inc bx
    inc bx

    这两条指令执行前 bx = 1002H,执行后 bx = 1004H。

    附图:

  6. 接下来,第10条指令:mov [bx], ax

    指令执行前:ds = 2000H,bx = 1004H,则 mov [bx], ax 将把 ax 中的数据送入内存 2000:1004 处。

    指令执行后,2000:1004 单元的内容为 BE,2000:1005 单元的内容为 00。

  7. 接下来,第11条指令:inc bx。这条指令执行前 bx = 1004H,执行后 bx = 1005H。

    附图:

  8. 接下来,第12条指令:mov [bx], al

    指令执行前:ds = 2000H,bx = 1005H,则 mov [bx], al 将把 al 中的数据送入内存 2000:1005 处。指令执行后,2000:1005 单元的内容为 BE。

    附图:

  9. 接下来,第13条指令:inc bx。这条指令执行前 bx = 1005H,执行后 bx = 1006H。

    附图:

  10. 接下来,第14条指令:mov [bx], al

指令执行前:ds = 2000H,bx = 1006H,则 mov [bx], al 将把 al 中的数据送入内存 2000:1006 处。指令执行后,2000:1006 单元的内容为 BE。

附图:

### Loop 指令

  • 格式:loop 标号
  • CPU执行loop指令的时候,要进行两步操作:
    1. (cx) = (cx) - 1;
    2. 判断 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,4c00hint 21 表示程序结束,键入debug的 p 命令结束程序;接着键入debug的q命令退出Debug。键入 exit 退出终端。

附图:

小结

从上边的课程中,我们可以总结出用 cx 和 loop 指令相配合实现循环功能的三个要点:

  1. 在 cx 中存放循环次数;
  2. loop指令中的标号所标识地址要在前面;
  3. 循环执行的程序段,要写在标号和loop指令的中间。

用 cx 和 loop 指令相配合实现循环功能的程序框架如下:

mov cx,循环次数
s:
循环执行的程序段
loop s

指令 loop s 会做三件事:

  1. (cx) = (cx) - 1;
  2. 判断 cx 中的值,不为零则转至标号(s)处执行程序;
  3. 如果为零则向下执行。

温故而知新

  • [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中。

  1. 在Debug中编程实现
  2. 汇编程序实现

两种实现的实际实施情况

在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指令相关推荐

  1. 《汇编语言》第5章 [BX]和loop指令

    1.[bx]和内存单元的描述 [bx]是什么呢?和[0]有些类似,[0]表示内存单元,它的偏移地址是0.比如在下面的指令中(在debug中使用): mov ax,[0] 将一个内存单元的内容送入ax, ...

  2. 《汇编语言》第5章 [BX]和loop指令——实验4[bx]和loop的使用

    本篇是第5章的实验--[bx]和loop的使用 (1)编程,向内存0:200~0:23F依次传送数据0~63(3FH). 解答: assume cs:codesg codesg segmentmov ...

  3. [BX]和loop指令03 - 零基础入门学习汇编语言25

    第五章:[BX]和loop指令03 让编程改变世界 Change the world by program 从上边的课程中,我们可以总结出用cx和loop 指令相配合实现循环功能的三个要点: (1)在 ...

  4. [BX] 和 loop 指令---汇编学习笔记

    [BX] 和 loop 指令 [bx]和内存单元的描述 loop 我们定义的描述性的符号:"()","()"中的元素可以有3中类型:寄存器名.段寄存器名.内存单 ...

  5. [bx]和loop指令编程

    [bx]和loop指令编程 一. 实验目的 二.实验内容 三. 实验步骤 四. 结果 五. 心得体会 六. 实验与思考 一. 实验目的 1.掌握[bx]和loop指令的用法. 2.结合已学知识灵活应用 ...

  6. [bx]与loop指令

    [bx]与loop指令 文章目录 [bx]与loop指令 1.[bx]与loop指令概念 2.[bx]和loop的联合应用 3.段前缀概念 4.包含多个段的程序案例 1.[bx]与loop指令概念 [ ...

  7. 汇编语言知识点总结之五:第五章《[bx]和loop指令》

    1.[bx]和内存单元的描述 [0]表示内存单元,它的偏移地址是0.比如在Debug中使用,如下指令: mov ax, [0] 代表:将一个内存单元的内容送入ax,这个内存单元的长度为2字节(字单元) ...

  8. 汇编(六):[BX] 和 Loop 指令

    文章目录 [bx] Loop指令 Debug 和汇编编译器 Masm 对指令的不同处理 loop 和 [bx] 的联合应用 段前缀 一段安全的空间 段前缀的使用 [bx] 1.[bx]是什么呢? 和[ ...

  9. [汇编语言][bx]和loop指令

    目录 一.[bx]与loop基本描述 二.[BX] 三.Loop指令 四.在Debug中跟踪用loop指令实现的循环程序 五.Debug和汇编编译器masm对指令的不同处理 六.loop和[bx]的联 ...

最新文章

  1. linux 集群配置ssh无密码访问
  2. 清华大学「天机」芯片登上Nature封面:类脑加传统计算融合实现通用人工智能...
  3. pmp每日三题(2022年3月14日)
  4. 自动化测试遇到的难点_自动化测试过程中遇到的问题主要有什么?
  5. oracle仲裁磁盘是一块磁盘吗,基于ASM冗余设计的架构,仲裁磁盘组应该如何去规划?...
  6. python 整数最大_Python程序使用floor()方法查找最大整数
  7. codeforces 816 B. Karen and Coffee(思维)
  8. click Commands and Groups
  9. 水泵怎么做_燃气壁挂炉初次调试,要怎么做才好?
  10. 中小企业电子商务如何发展?
  11. php 去除 ufeff,PHP去掉诡异的BOM \ufeff
  12. 改变Ubuntu18.04初始键盘布局
  13. 快速在服务器上搭建Halo个人博客
  14. 快速搭建简单图床 - 远程访问本地搭建的EasyImage图床【内网穿透】
  15. matlab 差分方程的解(解答qq网友)
  16. 光猫桥接后宽带降速问题解决
  17. 电脑预装linux系统,电脑预装Linux第三方系统怎么破?看外行人重装Win10系统的精准攻略...
  18. USB 协议 (五) 枚举
  19. 【数字化】“网络效应”指南:13 种网络效应全解析,带你了解巨头成功的秘密
  20. ES6新特性----面试

热门文章

  1. SMETA验厂辅导,贸易公司、物流仓储公司是否可以申请SMETA审核
  2. IBuySpy 网上商店的设计和实现
  3. 双核处理器的双核是什么意思?
  4. Google Earth Engine(GEE)——全球洪水数据库 v1 (2000-2018年)
  5. 【UCIe】UCIe DLP/DLLP 介绍
  6. Pandas的MultiIndex多层索引使用
  7. cad标注文字避让lisp_请教大家如何将标注标准设定“文字位置设置为置中”
  8. Jupyter中的魔法函数
  9. pack 和 unpack
  10. 秀一下大连TimesTen 18.1培训的结业证