这一章主要介绍什么是[BX]以及loop(循环)指令怎么使用,loop和[BX]又怎么样相结合,段前缀又是什么鬼,以及如何使用段前缀。
 
1、[BX]的概念
     [BX]和[0]类似,[0]表示内存单元的偏移地址是0。要完整描述一个内存单元,需要两种信息:内存单元的地址,内存单元的长度(类型)。[BX]同样也表示一个内存单元,它的偏移地址在bx中,比如指令:mov ax,[bx]。这里我们以一个程序为例:
      assume cs:codesg
codesg segment
start: mov ax,2000H
mov ds,ax
mov al,[]
mov bl,[]
mov cl,[]
mov dl,[]
mov ax,4C00H
int 21H
codesg ends
end start
     进行编译,连接之后,使用debug来调试这个程序。对于编译器而言,[0]的中括号是不存在的,所以会出现把0放到al中,把1放到bl中。所以,我们要想偏移地址为某个数,所对应的内存单元传递到寄存器当中,就需要进行两步操作:
     mov bx,0
     mov ax,[bx]
     这样做的话,就可以实现将偏移地址为0对应的内存单元的值传递给寄存器了。
 
2、loop
     这是一个做循环操作的指令,指令格式:loop 标号。
     CPU执行loop指令时,要进行两个步骤的操作:
          (1)(cx)=(cx)-1(这里的cx放在一个括号里面,意思是cx的值)
          (2)判断cx是不是为零,不为零的话转到标号出执行程序。
     所以,loop和cx是有直接联系的,即cx的值影响着loop的执行结果。所以cx的值也就是指的是loop的循环次数,我们可以想到高级语言中,使用循环时(比如for循环),我们都会定义一个变量,来作为循环的条件,这个变量的值也就是循环的次数。
     现在我们来看用汇编来计算2^2结果的代码:
 assume cs:code
code segment
mov ax,
add ax,ax mov ax,4c00h
int 21h
code ends
end
     计算2^3也是类似的,代码如下:   
 assume cs:code
code segment
mov ax,
add ax,ax
add ax,ax mov ax,4c00h
int 21h
code ends
end
     那么计算2^12,我们就要使用循环来做了,不然重复的代码太多,这个时候我们就要使用到loop指令了,代码如下:
 assume cs:code
code segment
mov ax,
mov cx,
s:add ax,ax
loop s mov ax,4c00h
int 21h
code ends
end
     上面的代码中,s就是标号,这个标号可以是任何你自己定义的内容,实际上s标明了一个地址,这个地址处有一个指令:add ax,ax。cx我们定义的值为11,因为要算2^12,所以要循环11次。循环时,cx会减1,循环一次减一次,直到cx为0,停止循环。我们可以使用debug调试编译连接好的程序:
     
     从上面的内容,我们可以得到cx和loop指令互相配合的三个关键点:
     (1)、在cx中存放循环次数
     (2)、loop指令标号所标识的地址要在前面
     (3)、要循环执行的程序段,写在标号和loop指令之间。
 
3、loop和[bx]的联合使用
     我们先从几个问题入手:计算ffff:0~ffff:b单元中的数据的和,结果存储在dx中。
     (1)、运算后的结果是否会超出dx所能存储的值的范围?
          ffff:0~ffff:b内存单元中的数据是字节型数据,范围是0~256,12个这样的数据相加,结果是不会比65535更大的,因此dx中是可以存储下的。
     (2)、能够将ffff:0~ffff:b直接累加到dx当中呢?
          不行,因为ffff:0~ffff:b中的数据是8位的,不能直接加到16位寄存器dx中。
     (3)、能否将ffff:0~ffff:b中的数据累加到dl中,并设置(dh)=0,从而实现累加到dx中呢?
          不行,dl是一个8位寄存器,能容纳的数据的范围在0~255之间,ffff:0~ffff:b中的数据也是8位的,将12个8位的数据累加到一个8位寄存器中,可能会出现进位丢失的情况。
     (4)、那么到底应该怎样将这段内存单元中的数据的和存储到dx中呢?
          就是使用一个16位寄存器来做中介,将内存单元中的8位数据赋值到一个16位寄存器ax中,再将这个ax中的数据加到dx上,从而使得运算对象的类型能够的到匹配(ax,dx都是16进制)并且结果不会越界。
     因为这里要进行12次的相加,因此要使用到loop指令进行循环相加的操作,具体代码如下:
 assume cs:codeseg
codeseg segment mov ax,0ffffh
mov ds,ax ;初始化ds:bx 指向ffff:0内存单元
mov bx, mov dx, ;初始化累加寄存器dx
mov cx, ;初始化循环计数寄存器cx s: mov al,[bx]
mov ah,
add dx,ax ;间接向dx中加上((ds)*16+(bx))单元中的数值
inc bx ;ds:bx指向下一个单元
loop s mov ax,4c00h
int 21h codeseg ends
end
 
4、Debug的G命令和P命令
     当我们对程序进行调试时,循环的次数很大时,我们不可能一次一次的执行t命令,因此要使用G命令或者P命令。G 循环结束的偏移地址,这样就可以一次执行完循环的内容。P,直接执行完循环的内容。
 
5、一段安全的空间
     当我们要直接向内存中写入内容时,这段内存空间不应该存放系统或者其它程序的数据或者代码,否则写入会导致操作系统发生错误,
DOS方式下,一般情况,0:200~0:2FF空间汇中没有存放系统或者其它程序的数据或者代码,以后我们写入内存就直接写到这段空间当中。
 
6、段前缀
     指令 mov ax,[bx]中,内存单元的偏移地址由bx给出,而段地址默认在ds中,我们可以在访问内存单元的指令中,显示的给出内存单元的段地址所在的段寄存器,比如,mov ax,ds:[bx],这里的段寄存器可以是ds,cs,es,ss,这些指令中的段寄存器在汇编语言中也被称为段前缀。
 
7、段前缀的使用
     首先我们考虑一个问题:将ffff:0~ffff:b中的数据复制到0:200~0:20b单元中。
     分析:
     (1)0:200~0:20b也就是0020:0~0020:b,它们描述的是同一个内存空间。
     (2)在循环中,源始单元 ffff:X 和目标单元 0200:X 的偏移地址X是变量,我们使用一个寄存器bx来存放
     代码如下:
 assume cs:codeseg
codeseg segment mov bx, ;偏移地址从0开始
mov cx, ;循环次数为12次 s: mov ax,0ffffh
mov ds,ax ;ds的值为0ffffh
mov dl,[bx] ;(dl)=((ds)*16+bx)将ffff:bx中的数据传入到dl中 mov ax,0020h
mov ds,ax ;ds的值为0020h
mov [bx],dl ;((ds)*16+bx)=(dl)将dl中的数据传入到0020:bx中 inc bx ;bx自增1
loop s mov ax,4c00h
int 21h codeseg ends
end
     
  当然,我们上面的代码还有需要改进的地方,从上面的代码可以看到,我们重复设置了两次ds的值,这样做没有错,只是在循环的次数比较小的情况下,一旦循环的次数增到很大时,CPU就要进行很多次重复的操作,这样效率也就比较低了。因此,我们可以对代码进行相应的改进:

 assume cs:codeseg
codeseg segment
mov ax,0ffffh
mov ds,ax ;(ds)=0ffffh mov ax,0020h
mov es,ax ;(es)=0020h mov bx, ;(bx)=0,这个时候,ds:bx指向ffff:0,es:bx指0020:0
mov cx, s:
mov dl,[bx] ;(dl)=((ds)*16+(bx)),将ffff:bx中的数据传入到dl
mov es:[bx],dl ;((es)*16+(bx))=(dl),将dl中的数据传入0020:bx inc bx
loop s mov ax,4c00h
int 21h codeseg ends
end

小甲鱼零基础汇编语言学习笔记第五章之[BX]和loop指令的更多相关文章

  1. 小甲鱼零基础汇编语言学习笔记第二章之寄存器(CPU工作原理,CPU内部通讯)

    这一章主要介绍了CPU中的重要器件——寄存器,整个系列通篇是以8086CPU作为探讨对象,其它更高级的CPU都是在此基础之上进行的升级.   1.一个典型的CPU是由运算器.控制器.寄存器等器件组成, ...

  2. 小甲鱼零基础入门学习python--课后作业

    [小甲鱼零基础入门学习python--课后作业] 小甲鱼零基础入门学习python--课后作业 本章内容: 1.基础部分的作业 2.函数部分的作业 3.字典.集合.文件部分作业 4.异常 5.Easy ...

  3. 小甲鱼零基础学python第25讲课后习题动手练习--通讯录

    小甲鱼零基础学python第25讲课后习题动手练习---通讯录 **************************通讯录要求******************************* 输入指令: ...

  4. Programming Entity Framework-dbContext 学习笔记第五章

    ### Programming Entity Framework-dbContext 学习笔记 第五章 将图表添加到Context中的方式及容易出现的错误 方法 结果 警告 Add Root 图标中的 ...

  5. [HeadFrist-HTMLCSS学习笔记]第五章认识媒体:给网页添加图像

    [HeadFrist-HTMLCSS学习笔记]第五章认识媒体:给网页添加图像 干货 JPEG.PNG.GIF有何不同 JPEG适合连续色调图像,如照片:不支持透明度:不支持动画:有损格式 PNG适合单 ...

  6. [汇编学习笔记][第五章[BX]和loop指令]

    第五章[BX]和loop指令 前言 定义描述性符号“()”来表示一个寄存器或一个内存单元的内容,比如: (ax)表示ax中的内容,(al)表示al的内容. 约定符号ideta表示常量. 5.1 [BX ...

  7. 改进我们的小游戏 - 零基础入门学习Python004

    改进我们的小游戏 让编程改变世界 Change the world by program 改进我们的小游戏 很多鱼油对改善这个游戏提出了建议,小甲鱼做了一下总结,大概有以下几个方面需要改进: 猜错的时 ...

  8. 小甲鱼零基础python课后题 P22 021函数:递归是神马

    0.递归在编程上的形式是如何表现的呢? 答:在编程上,递归表现为函数调用本身这么一个行为. 1.递归必须满足哪两个基本条件? 答:1函数调用自己. 2有正确的返回条件 2.思考一下,按照递归的特性,在 ...

  9. Python基础教程学习笔记:第一章 基础知识

    Python基础教程 第二版 学习笔记 1.python的每一个语句的后面可以添加分号也可以不添加分号:在一行有多条语句的时候,必须使用分号加以区分 2.查看Python版本号,在Dos窗口中输入“p ...

随机推荐

  1. CSS3样式_实现字体发光效果

    text-shadow 属性仅仅是用来设置文本阴影的,似乎并不能实现字体发光效果.其实不然,这正是 text-shadow 属性的精妙之处.当阴影的水平偏移量和垂直偏移量都为0时,阴影就和文本重合了. ...

  2. bootstrap悬停下拉菜单显示

    使用Bootstrap导航条组件时,如果你的导航条带有下拉菜单,那么这个带下拉菜单的导航在点击时只会浮出下拉菜单,它本身的href属性会失效,也就是失去了超链接功能,这并不是我想要的,我希望导航条的链 ...

  3. SCOI 2010 连续攻击游戏(贪心,图论)

    SCOI 2010 连续攻击游戏 solution 直接就硬刚 我愿称贪心为暴力 因为题目中要求一定从小到大贪心,那么当前点的下标有能够选取的较大点,那么它一定可以和前面的一个较小点连接,所以可以直接 ...

  4. 简单了解一下 Swagger

    一.Swagger 1.什么是 Swagger ? Swagger 是一个规范和完整的框架,用于生成.描述.调用以及可视化的 Restful 风格的 Web 服务. 简单的理解:是一款 REST AP ...

  5. C++敲代码前的准备工作

    #pragma GCC target("avx,sse2,sse3,sse4,popcnt") #pragma GCC optimize("O2,Ofast,inline ...

  6. Report.Net 本地数据库、WebService、Socket报表

    本地.服务器的Access.Sql报表编辑.预览.打印. 可自定义预览界面,可方便嵌入到你的程序中去,提供接口函数,如有需要可自行添加接口. 预览采用单双面方式,因为如果页面过多,预览不能全部加载,所 ...

  7. Anbox补充:添加arm支持(失败!)

    写在开头: 本人是一边操作一边写博文的,折腾一下午写到最后失败了不舍得删,还是发上来记录一下我的操作,希望能有高人指点或者给同学们一点启发.以下的内容仅做观看即可,若无必要就不必尝试了. 之前写了一篇 ...

  8. python虚拟环境 + 批量pip + 换源

    python虚拟环境 + 批量pip + 换源 虚拟环境 曾经我是一个小白,不管运行什么项目都用一个环境,后来项目多了,有的是Django1.11的有的是Django2的,有的项目只能在3.6上运行, ...

  9. element-ui(vue版)使用switch时change回调函数中的形参传值问题

    需求说明 有多个switch组件 需要知道switch的状态 表格中当前行(scope.row)的数据 问题描述 官方文档中对switch中change的描述: 目前能得到switch的状态值,但是无 ...

  10. socket采用epoll编程demo

    epoll工作流程 首先,需要调用epoll_create创建epoll: 此后我们就可以进行socket/bind/listen: 然后调用epoll_ctl进行注册: 接下来,就可以通过一个whi ...