1、[bx]和内存单元的描述

[0]表示内存单元,它的偏移地址是0。比如在Debug中使用,如下指令:

mov ax, [0]

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

mov al, [0]

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

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

1)内存单元的地址;

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

我们用[0]表示一个内存单元时,0 表示单元的偏移地址,段地址默认在ds中,单元的长度(类型)可以由具体指令中的其他操作对象(比如说寄存器)指出,如前边的AX,AL。

[bx]同样也表示一个内存单元,它的偏移地址在bx中,比如下面的指令:

mov ax, [bx]

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

mov al, [bx]

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

描述性符号 ()

为了描述上的简洁,在以后的课程中,我们将使用一个描述性的符号 “() ”来表示一个寄存器或一个内存单元中的内容。

比如:(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))等是正确的用法;

(2000H)、(2000:0)、((ds):1000H) 等是不正确的用法;

我们看一下(X)的应用,比如:

(1)ax中的内容为0010H,我们可以这样来描述:(ax)=0010H;

(2)2000:1000 处的内容为0010H,我们可以这样来描述:(21000H)=0010H;

(3)对于mov ax,[2]的功能,我们可以这样来描述:(ax)=((ds)*16+2);

(4)对于mov [2],ax 的功能,我们可以这样来描述:((ds)*16+2)=(ax);

(5)对于 add ax,2 的功能,我们可以这样来描述:(ax)=(ax)+2;

(6)对于add ax,bx的功能,我们可以这样来描述:(ax)=(ax)+(bx);

(7)对于push ax的功能,我们可以这样来描述:

  • (sp) = (sp)-2
  • ((ss)*16+(sp))=(ax)

(8)对于pop ax 的功能,我们可以这样来描述:

  • (ax)=((ss)*16+(sp))
  • (sp)=(sp)+2

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

(al)、(bl)、(cl)等得到的数据为字节型;

(ds)、(ax)、(bx)等得到的数据为字型。

约定符号 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,l、mov bx,2、mov bx,3等。
  • mov ds,idata就代表mov ds,1、mov ds,2等,(是非法指令,段寄存器是需要中转的)

2、[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 :

程序和内存中的情况如下图所示,写出程序执行后,21000H~21007H 单元中的内容。

注意,inc bx的含义是bx中的内容加1,比如下面两条指令:

mov bx,1

inc bx

执行后,bx=2。

分析:

3、Loop指令

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

  • (cx)=(cx)-1;
  • 判断cx中的值,不为零则转至标号处执行程序,如果为零则向下执行。;总体而言,类似于do……while ,先执行一次,再进行判断。

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

编程任务1:编程计算2^3:

assume cs:code
code segmentmov ax,2add ax,axadd ax,axmov ax,4c00Hint 21H
code ends
end

便程任务2:编程计算2^12

分析:首先将ax初值设为2;然后2^12=ax*2*2*2*2*2*2*2*2*2*2*2; N*2可用N+N实现,程序如下:

assume cs:code
code segmentmov ax,2做11次 add ax,axmov ax,4c00Hint 21H
code ends
end

采用loop指令,重写程序:

assume cs:code
code segmentmov ax,2mov cx,11 //专门存放循环次数
s:  add ax,axloop smov ax,4c00Hint 21H
code ends
end

程序分析:

(1)标号
在汇编语言中,标号代表一个地址,此程序中有一个标号s 。它实际上标识了一个地址,这个地址处有一条指令:add ax,ax。

(2)loop s

CPU 执行loop s的时候,要进行两步操作:

① (cx)=(cx)-1;

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

(3)以下三条指令

mov cx,11

s: ddd ax,ax

loop s

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

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

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

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

mov cx, 循环次数

s:

循环执行的程序段

loop s

问题 5.2

编程,用加法计算 123*236,结果存在ax中。思考后看分析:

分析:可用循环完成,将123加236次。可先设(ax)=0,然后循环做236次(ax)=(ax)+123。

程序如下:

assume cs:code
code segmentmov ax,0mov cx,236
s:  add ax,123loop smov ax,4c00Hint 21Hcode ends
end

问题5.3

改进程序5.2,提高123*236的计算速度。思考后看分析。

分析:

程序5.2 做了236次加法,我们可以将236加123次。可先设(ax)=0,然后循环做123次(ax)=(ax)+236,这样可以用123次加法实现相同的功能。

小结:

(1)【bx】的作用:作为偏移地址与DS配合

在Debug中写过类似的指令:

  • mov ax,[0]
  • 表示将ds:0处的数据送入al中。

但是在汇编源程序中,指令“mov ax,[0]”被编译器当作指令“mov ax,0”处理。

示例任务:将内存2000:0、2000:1 、2000:2、2000:3单元中的数据送入al,bl,cl,dl中。

  • 在Debug中编程实现
  • 汇编程序实现

Debug编程如下所示:

    mov ax,2000hmov ds,axmov al,[0]mov bl,[1]mov cl,[2]mov dl,[3]

汇编源程序如下所示:

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中mov ax, [2]是解释为mov ax,2的。一般我们是通过BX来代替,像这道题我们先mov bx, 2 再通过mov ax, [bx]来实现。

即:mov a1,[0] 改为:mov bx,2 ; mov ax, [bx]

如下指令:

如果在汇编程序/masm中:

mov al, [0]    表示:(al)=0

mov al, ds:[0]  表示:段地址在ds中,偏移地址为0的内存,内存中的内容给al

mov al, [bx]  表示:从默认的段地址(ds的定义在此语句的前面),偏移地址为bx处,内存单元中的内容给al

mov al, ds:[bx]   表示:将段地址为ds,偏移地址为bx处,内存单元中的内容给al

(2)loop 和 cx 合作

loop是循环,cx存放的是循环的次数

(3)debug 的-g 偏移地址 命令 和 -p命令

4、在Debug中跟踪用loop指令实现的循环程序

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

6、段前缀

指令 “mov ax,[bx]”中,内存单元的偏移地址由bx给出,而段地址默认在ds中。我们可以在访问内存单元的指令中显式地给出内存单元地段地址所在地段寄存器。比如:

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

mov ax, ss:[0]

将一个内存单元地内容送入ax,这个内存单元地长度为2字节(字单元),存放一个字,偏移地址为0,段地址在ss中。

mov ax, cs:[0]

将一个内存单元地内容送入ax,这个内存单元地长度为2字节(字单元),存放一个字,偏移地址为0,段地址在cs中。

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

7、一段安全的空间

总结:

(1)我们需要直接向一段内存中写入内容;

(2)这段内存空间不应存放系统或其他程序的数据或代码,否则写入操作很可能引发错误。

(3)DOS方式下,一般情况, 0:200~0:2FF 空间中没有系统或其他程序的数据或代码;

(4)以后,我们需要直接向一段内存中写入内容时,就使用0:200~0:2FF这段空间。

8、段前缀的使用

问题:将内存 ffff:0 - ffff:b 单元中的数据拷贝到 0:200 - 0:20b单元中。

分析:

(1) 0:200~0:20b单元等同于0020:0~0020:b单元,它们描述的是同一段内存空间:

(2)拷贝的过程应用循环实现,简要描述如下:

  • 初始化:X=0
  • 循环12次:
  • 将ffff:X单元中的数据送入0020:X(需要用一个寄存器中转)
  • X=X+1

(3)在循环中,源单元 ffff:X 和目标单元的 0020:X 的偏移地址 X 是变量。我们用 bx 来存放。

(4)我们用将 0:200~0:20b 用 0020:0~0020:b 描述,就是为了使目标单元的偏移地址和源始单元的偏移地址从同一数值0开始。

程序如下:

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 bxloop smov ax,4c00Hint 21H
code ends
ends

上述程序分析:

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

改进程序如下:

assume cs:code
code segmentmov ax,0ffffhmov ds,ax ;(ds)=0ffffhmov ax,0020hmov es,ax ;(es)=0020hmov bx,0 ;(bx)=0,偏移地址从0开始,此时ds:bx指向ffff:0,es:bx指向0020:0mov cx,12 ;(cx)=12,循环12次
s:  mov dl,[bx] ;(dl)=((ds)*16+(bx)),将ffff:bx中的数据送入dlmov es:[bx],dl ;((es)*16+(bx))=(dl),将dl的数据送入0020:bxinc bxloop smov ax,4c00Hint 21H
code ends
ends

程序分析:

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

实验 4 [bx]和loop的使用

1、编程,向内存 0:200 - 0:23F依次传送数据 0-63(3FH),程序中只能使用9条指令,9条指令中包括 “mov ax 4c00H” 和 “int 21H”。

代码如下:

assume cs:code
code segmentmov ax,0020Hmov ds,axmov bx,0mov cx,40h    ;或mov cx,64
s:  mov [bx],bxinc bxloop smov ax,4c00Hint 21Hcode ends
ends

2、下面程序的功能是将“mov ax, 4c00H” 之前的指令复制到内存 0:200处,补全程序。

提示:

  • 复制的是什么?从哪里到哪里?
  • 复制的是什么?有多少个字节?读者如何知道要复制的字节的数量?

答案:

assume cs:code
code segment   mov ax, code ;或mov ax, cs mov ds,ax   mov ax,0020h   mov es,ax   mov bx,0   mov cx, 18h   ;或mov cx, 17h    ;或sub cx,5s: mov al,[bx]   mov es:[bx],al   inc bx   loop s   mov ax,4c00h   int 21h
code ends
end

此题有多个答案,因为mov用在寄存器之间传送数据的指令是2个字节,用在寄存器和立即数之间是3个字节

答案1:mov ax,cs  (占2个字节)

mov cx,17

答案2:mov ax,code (占3个字节)

mov cx,18

答案3:mov ax,cs 或mov ax,code

把mov cx, 改成 sub cx,5

(因为在载入程序时,cx保存程序的长度,减去5是为减去mov ax,4c00h和int 21h的长度)

此题的目的是:

1、理解CS和CODE的关联

2、理解CS保存程序的代码段,即“复制的是什么,从哪里到哪里”

3、理解CX在载入程序后保存程序的长度。

4、理解数据和代码对CPU来说是没区别的,只要CS:IP指向的就是代码

汇编语言知识点总结之五:第五章《[bx]和loop指令》相关推荐

  1. 第五章 [BX]和loop指令

    5.1 [bx] [bx]是什么 和 [0] 有些类似,[0] 表示内存单元,它的偏移地址是 0. 例如: mov ax, [0] 内存以字节为单位:ax以字(16bit = 2Byte)为单位:al ...

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

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

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

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

  4. 开发日记-20190914 关键词 汇编语言王爽版 第五章

    第五章 [BX]和loop指令 5.2 Loop指令 loop指令的格式是:loop标号,CPU执行loop指令的时候,要进行两步操作, (cx)=(cx)-1 判断cx中的值,不为零则转至标号处执行 ...

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

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

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

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

  7. [bx]与loop指令

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

  8. [bx]和loop指令编程

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

  9. 概率论||期末考试复习手写笔记-第五六七章(知识点+例题)第五章 常用统计分布 第六章 参数估计 第七章 假设检验

    第五章  常用统计分布 考点一:常用统计量 考点二:三大统计分布 考点三:抽样分布(单正态总体+双正态总体) 第六章 参数估计 考点一: 估计量的评价标准(无偏性+有效性+相合性) 考点二:点估计的常 ...

最新文章

  1. 黑马程序员Linux系统开发视频之创建守护进程模型
  2. Algorithm:C++语言实现之分治法相关问题(给定实数x和整数n,分治法求xn)
  3. UICollectionView实现的图片的多选效果(本人已封装好,简单操作)
  4. NOIP2013货车运输
  5. Java IO: 并发IO
  6. oracle 集群 配置,Oracle集群配置
  7. ZooKeeper入门指南
  8. 利用Shell将MySQL数据表导出为csv文件
  9. qq等级查询php源码,最新沉沦QQ等级代挂系源码统开源分享
  10. ROS ros::NodeHandle nh(“~“)
  11. 视频会议系统架构和开源解决系统
  12. 内窥镜胶囊(胶囊内镜)硬件方案
  13. 剖析Linux的守护神
  14. git切换远程分支为develop
  15. 用户管理和用户组管理
  16. 【Unity笔记】连招动画切换方式(一)
  17. iOS应用跳转(包括iPhone原有应用跳转和第三方应用跳转)
  18. 一个月提升口语听力n个level
  19. 站多久可以“抵消”久坐伤害?世卫组织推荐这个时间!
  20. 读书笔记-代码的未来

热门文章

  1. 中国美容美发市场需求现状与投资价值分析报告2022年版
  2. DNSRecon 域名信息查询
  3. DNS BIND 搭建域名智能解析DNS服务器之IP地址归类(ACL)
  4. 一、node.js的理解?优缺点?应用场景?
  5. 计算机大师( 一 ) COMPUTER MASTERS (1)
  6. 儿童身高体重记录检测表
  7. 给程序员的10条中肯建议
  8. 根据实测高程值校正DSM高程
  9. cgic 写CGI程序
  10. [转]用Mcafee打造自己的安全系统