首先定义一下符号:

描述性符号: “()”

为了描述上的简洁,我们使用一个描述性的符号"()"来表示一个寄存器或一个内存单元中的内容,比如:

  • (ax)表示ax中的内容、(al)表示al中的内容。
  • (20000H)表示内存20000H单元的内容。
  • ((ds)*16+(bx))表示ds中的内容为ADR1,bx中的内容为ADR2,内存ADR1*16+ADR2单元的内容。这同样可以理解为,ds中的ADR1作为段地址,bx中的ADR2作为偏移地址,内存ADR1:ADR2单元的内容。

注意"()"中的元素可以有三种类型:寄存器名、段寄存器名、内存单元的物理地址(一个20位数据)。比如:

(ax)、(ds)、(al)、(cx)、(20000H)、((ds)*16+(bx))等是正确的用法。

我们来看下(X)的应用:

  • ax中的内容为0010H,可以这样来描述:(ax)=0010H
  • 2000:1000处的内容为0010H,可以这样来描述:(21000H)=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的功能,可以这样来描述:
    (sp)=(sp)-2
    ((ss)*16+(sp))=(ax)
  • 对于pop ax的功能,可以这样来描述:
    (ax)=((ss)*16+(sp))
    (sp)=(sp)+2

注意(X)所表示的数据有两种类型,字节和字,是哪种类型由寄存器名或具体的运算决定,比如:

  • (al)、(bl)、(cl)等得到的数据为字节型;(ds)、(ax)、(bx)等得到的数据为字型
  • (al)=(20000H)得到的数据为字节型;(ax)=(20000H)得到的数据为字型

符号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等

一、[BX]

[bx]和[0]有些类似,[0]表示段地址在ds中,偏移量为0的内存单元,[bx]同样也表示一个内存单元,它的偏移地址在bx中,比如下面的指令:

mov ax,[bx]

将一个内存单元中的内容送入ax,这个内存单元的长度为2字节(字单元),存放一个字,偏移地址在bx中,段地址在ds中。即:(ax)=((ds)*16=(bx))

mov al,[bx]

将一个内存单元的内容送入al,这个内存单元的长度为1字节(字节单元),存放一个字节,偏移地址在bx中,段地址在ds中

二、Loop指令

loop指令的格式是:loop 标号,CPU执行loop指令的时候,要进行两步操作:

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

从上面的描述中,可以看到,cx中的值影响着loop指令的执行结果。通常我们用lool指令来实现循环功能,cx中存放循环次数。

接下来通过一个程序来看下loop指令的具体应用:

任务1:编程计算222^222,结果存在ax中。

设(ax)=2(ax)=2(ax)=2,可计算(ax)=(ax)×2(ax)=(ax)\times2(ax)=(ax)×2,最后(ax)(ax)(ax)中为222^222的值。N×2N\times2N×2可用N+NN+NN+N实现,程序如下:

assume cs:code
code segmentmov ax,2add ax,axmov ax,4c00hint 21h
code ends
end

但是按照上面的算法,计算2122^{12}212需要11条重复的指令 add ax,ax。这种情况下,我们就可以用loop来简化我们的程序。

程序5.1

assume cs:code
code segmentmov ax,2mov cx,11
s:  add ax,axloop smov ax,4c00hint 21h
code ends
end

接下来分析下程序5.1

(1)标号
在汇编语言中,标号代表一个地址,程序5.1中有一个标号s。它实际上标识了一个地址,这个地址处有一条指令:add ax,ax
(2)loop s
CPU执行loop s的时候,要进行两步操作

  1. (cx)=(cx)-1
  2. 判断cx中的值,不为0则转至标号s所标识的地址处执行(这里的指令是add ax,ax),如果为零则执行下一条指令(下一条指令是mov ax,4c00h)

(3)以下三条指令

 mov cx,11
s:  add ax,axloop s

执行loop s时,首先要将(cx)减一,然后若(cx)不为0,则向前转至s处执行add ax,ax。所以,可以利用cx来控制add ax,ax的执行次数。

用cs和loop指令相配合实现循环功能的3个要点:

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

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

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

五、loop和[bx]的联合应用

考虑这样一个问题,计算ffff:0~ffff:b单元中的数据的和,结果存储在dx中。

分析下可能出现的问题:

  • 运算后的结果是否会超出dx所能存储的范围?
    ffff:0~ffff:b内存单元中的数据是字节型数据,范围在0~255之间,12个这样的数据相加,结果不会大于65535,可以在dx中存放下
  • 能否将ffff:0~fff:b中的数据直接累加到dx中?
    不可以,因为ffff:0~ffff:b中的数据都是8位的,不能直接加到16位寄存器dx中
  • 能否将ffff:0~ffff:b中的数据累加到dl中,并设置(dh)=0,从而实现累加到dx中?
    这也不行,因为dl是8位寄存器,能容纳的数据的范围在0~255之间,ffff:0~ffff:b中的数据也都是8位,如果仅向dl中累加12个8位数据,有可能造成进位丢失

从上面的分析中,可以看出两个主要问题:类型的匹配和结果的不越界。解决的方法就是用一个16位寄存器来做中介,将内存单元中的8位数据赋值到一个16位寄存器ax中,再将ax中的数据加到dx上,从而使得两个运算对象的类型匹配并且结果不会越界。

程序如下:

程序5.5

assume cs:codecode segmentmov ax,ffffhmov ds,ax              //设置(ds)=ffffhmov dx,0                   //初始化累加寄存器,(dx)=0mov al,ds:[0]mov ah,0                    //(ax)=((ds)*16+0)=(ffff0h)add dx,ax             //向dx中加上ffff:0单元的数值mov al,ds:[1]mov ah,0                 //(ax)=((ds)*16+1)=(ffff1h)add dx,ax             //向dx中加上ffff:1单元的数值mov al,ds:[2]mov ah,0                 //(ax)=((ds)*16+2)=(ffff2h)add dx,ax             //向dx中加上ffff:2单元的数值..........mov al,ds:[0bh]mov ah,0                 //(ax)=((ds)*16+0bh)=(ffff0bh)add dx,ax              //向dx中加上ffff:0bh单元的数值mov ax,4c00h            //程序返回int 21hcode ends
end

上面的程序很简单,但是存在大量重复。所以可以使用loop来改进上面的程序:

程序5.6

assume cs:code
code segmentmov ax,0ffffhmov ds,axmov bx,0              // 初始化ds:bx指向ffff:0mov dx,0               //初始化累加寄存器dx,(dx)=0mov cx,12          //初始化循环计数寄存器cx,(cx)=12s:  mov al,[bx]mov ah,0add dx,ax            //间接向dx中加上((ds)*16+(bx))单元的数值inc bx                  //ds:bx指向下一个单元loop smov ax,4c00hint 21hcode ends
end

六、段前缀

我们可以在访问内存单元的指令中显式地给出内存单元的段地址所在的段寄存器。比如:

  • mov ax,ds:[bx]
    将一个内存单元的内容送入ax,这个内存单元的长度为2字节(字单元),存放一个字,偏移地址在bx中,段地址在ds中。
  • mov ax,cs:[bx]
    将一个内存单元的内容送入ax,这个内存单元的长度为2字节(字单元),存放一个字,偏移地址在bx中,段地址在cs中
  • mov ax,ss:[bx]
    将一个内存单元的内容送入ax,这个内存单元的长度为2字节(字单元),存放一个字,偏移地址在bx中,段地址在ss中
  • mov ax,es:[bx]
    将一个内存单元的内容送入ax,这个内存单元的长度为2字节(字单元),存放一个字,偏移地址在bx中,段地址在es中

这些出现在访问内存单元的指令中,用于显式地指明内存单元的段地址的"ds:", “cs:”, “ss:”, “es:”,在汇编语言中称为段前缀。

七、段前缀的使用

考虑一个问题,将内存ffff:0~ffff:b单元中的数据复制到0:200~0:20b单元中。

程序如下:

程序5.8

assume cs:code
code segmentmov bx,0                    //(bx)=0,偏移地址从0开始mov cx,12                //(cx)=12,循环12次s: mov ax,0ffffhmov ds,ax              //(ds)=0ffffhmov dl,[bx]             //(dl)=((ds)*16+(bx)),将ffff:bx中的数据送入dlmov ax,0020hmov ds,ax                //(ds)=0020hmov [bx],dl              //((ds)*16+(bx))=(dl),将dl的数据送入0020:bxinc bx                        //(bx)=(bx)+1 loop smov ax,4c00hint 21hcode ends
end

因源始单元ffff:X和目标单元0020:X相距大于64KB,在不同的64KB段里,程序5.8中,每次循环要设置两次ds。这样做是正确的,但是效率不高。我们可以使用两个段寄存器分别存放源始单元ffff:X和目标单元0020:X的段地址,这样就可以省略循环中需要重复做12次的设置ds的程序段。

改进的程序如下:

程序5.9:

assume cs:code
code segmentmov ax,0ffffhmov ds,axmov ax,0020hmov es,axmov bx,0mov cx,12s:  mov dl,[bx]mov es:[bx],dlinc bxloop smov ax,4c00hint 21hcode ends
end

程序5.9中,使用es存放目标空间0020:0~0020:b的段地址,用ds存放源始空间ffff:0~ffff:b的段地址。在访问内存单元的指令"mov es:[bx],al"中,显式地用段前缀"es:"给出单元的段地址,这样就不必在循环中重复设置ds。

BX+CX+loop相关推荐

  1. 按照下列给定步骤完成求累加和程序: 程序: MOV BX,1000 MOV CX,10 MOV AL,0 LOP: ADD AL,[BX] INC BX J: LOOP LOP INT

    按照下列给定步骤完成求累加和程序: 程序: MOV BX,1000 MOV CX,10 MOV AL,0 LOP: ADD AL,[BX] INC BX J: LOOP LOP INT3 步骤: 1) ...

  2. 实验四 [bx]和loop的使用+段前缀

    [bx]和loop的使用 (1)编程,向内存0:200~0:23F依次传送数据0 ~63(3FH) assume cs:code code segmentmov ax,20Hmov es,ax;数据传 ...

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

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

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

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

  5. [bx]与loop指令

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

  6. [bx]和loop指令编程

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

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

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

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

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

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

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

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

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

最新文章

  1. 如何从字符串中删除文本?
  2. ios8 UITableView section不显示
  3. linux安装Python2.7
  4. 实体类的动态生成(三)
  5. ubuntu安装配置方法【转】
  6. 「PKUSC2018」神仙的游戏 - 题解
  7. 服务器对操作系统有什么要求,服务器对操作系统有什么要求
  8. weka特征选择源码阅读
  9. [bzoj3527][Zjoi2014]力
  10. FireFox 在新建标签页插入“片段”广告引社区争议
  11. springsecurity安全登录框架
  12. k2p升级显示服务器错误,k2p—b1版本刷固件遇到的问题
  13. 计算机无法安装新字体,如何解决XP系统中无法安装新字体
  14. html表单 新页面打开新页面,js提交表单并打开新页面的方法
  15. python体重转换_Python第十二课 计算体脂率2.0
  16. Autojs对接图灵机器人
  17. Discuz模板制作教程
  18. 电竞级还带主动降噪,莱仕达X2无线蓝牙耳机实测,品控值得安利
  19. 无锡技师学院计算机教师,无锡技师学院5位老师国赛战绩耀眼
  20. CentOS6 图形界面(gnome)安装

热门文章

  1. IDL实现矢量(shp)裁剪栅格TASK(一)
  2. Navicat Premium 12安装过程
  3. windows32位安装MongoDB
  4. 2 java内存模型是什么_java中内存模型是什么?有什么用?
  5. android通用对话框,android-所有活动中的“通用”对话框
  6. 详解如何实现斗鱼、B站等全局悬浮窗直播小窗口
  7. VLC框架总结(一)VLC源码及各modules功能介绍
  8. linux .net环境变量,Linux编程 系统环境变量位置, 环境变量持久化
  9. python脚本读书心得_《利用Python进行数据分析》读书笔记(一)Python Basic
  10. android log4j slf4j,Android中的LOG4J