80806汇编(5)——[BX]和Loop指令

已经好久没写点东西了,国庆节就一直想弄个个人网站,这段时间一直在弄那个,虽然有现成的框架(Hexo),但是总想弄出自己的效果来,但是最后还是有些差强人意,只好打翻了有重来(强迫症表示难受),也懒得弄那么多了。好在最近差不多事情也理顺了,今天强迫自己静下来写了点东西。

[TOC]


简述

今天看了下汇编中的[BX]和Loop指令,Loop指令容易知道,一看就是用来做循环的指令,那么[BX]又是什么呢?

首先我们知道,要完整的描述一个内存单元,需要两种信息:

  • 内存单元的地址
  • 内存单元的长度(类型:字节或字等)

对于第一个——【内存单元的地址】,我们知道,用[addr]可以表示一个内存单元,其中addr表示这个内存单元的偏移地址,段地址默认在DS寄存器中。而单元的长度(类型)则可以由指令中的其他操作对象指出(如寄存器),就像下面这样:

mov ax, [0]

那么,在这里[BX]也表示一个内存单元,其偏移地址存于BX寄存器中,段地址默认在DS寄存器中。也把BX寄存器叫做基址寄存器

两个约定

为了方便后面的叙述,这里作两个约定,当然也是跟着书上的来啦,哈哈,不过我发现很多书上也都默认有这个叙述方法。

1. 描述性符号"( )"

用描述性符号“( )”表示一个寄存器或一个内存单元中的内容,如:

(ax) 表示寄存器AX中的内容,(al) 表示寄存器AL中的内容。
(addr) 表示物理地址为addr的内存单元中的内容。

因此"( )"中的元素类型有3种:

  1. 寄存器名;
  2. 段寄存器名;
  3. 内存单元的物理地址。

其所表示的数据类型有:

  1. 字节;
  2. 字。

具体是那种类型则由寄存器名或具体的运算符决定。

2. 常量符号"idata"

用idata表示一个常量。

如用mov ax, [idata]代表mov ax, [1]mov ax, [2]等。

如用mov bx, idata代表mov bx, 1mov bx, 2等。

[BX]

我们对[BX]的使用有如下用法:

mov ax, [bx]  ; bx中存放的数据作为偏移地址,段地址默认在ds中,(ax) = ((ds) * 16 + (bx))
mov [bx], ax  ; bx中存放的数据作为偏移地址,段地址默认在ds中,((ds) * 16 + (bx)) = (ax)

Loop指令

Loop指令用于实现循环功能,循环次数存于CX寄存器中 。

【格式】loop 标号

示例:

mov cx, 5      ; 设置循环次数
s:                  ; 标号
add ax, ax     ; 循环执行的程序段
loop s           ; Loop指令

Loop指令通常用于执行某些需要重复运行的指令,比如操作某一块连续的内存地址块。通常把循环次数存于CX寄存器中,CPU通过判断CX里面的值是否为零来决定是否执行循环。CPU执行Loop指令的描述如下:

1. (CX) = (CX) -1
2. (CX)不为零,转去标号处执行,反之不执行循环,向下执行指令

这里的标号"s"并不是固定的,你也可以指定其他的标号。在这里标号实际上是标识了一个地址,在该地址处存在着我们的程序指令(如上面的add ax, ax),在执行循环的时候,若CX的值不为零,则"Loop 标号"指令将IP的值设置为标号所标识的地址,CPU就将执行IP所指向的指令。

我们可以得到这样一个Loop指令的简单框架:

mov cx, 循环次数
label:
需要循环执行的程序段
loop label

【注意】书上的一个实例程序中提到在汇编程序中的数据表示问题,我们知道,在汇编中,数据多以16进制表示,而16进制中有 'A~F' 6个字母,但是在汇编源程序中,数据的书写不能以字母开头,如“9876H”可以直接书写为“9876H”,但是“A000H”不能书写成“A000H”,而需写为“0A000H”(以0开头)。

[BX]和Loop指令

在实际编程中可能会遇到要处理某一段地址连续的内存单元中的数据,通常可用循环来解决这类问题。在这样的循环过程中,需要一个变量来保存内存单元的偏移地址,这时候“基址寄存器——BX”就起作用了。

【注:以下内容来自王爽的《汇编语言》(第三版)】

考虑这么一个问题,我们要计算 ffff:0~ffff:b 单元中的数据的和,要求将结果存储在dx寄存器中。

我们首先分析一下:

  1. 运算后的结果是否会超出dx能存储的范围?

    ffff:0~ffff:b 内存单元中的数据是字节型的数据,范围在0~255之间,12个这样的数据相加的结果不会大于65535,是可以存储在dx寄存器中的。
  2. 我们能否将 ffff:0~ffff:b 中的数据直接累加到dx中?

    这是比不可能的,为什么?因为数据类型不匹配,dx是16位寄存器,而 ffff:0~ffff:b 中的数据是8位的。
  3. 那么是否可以将其累加到dl中,并设置(dh)=0,从而实现累加到dx中?

    看第一条分析,12个8字节的数据相加是有可能超过255的,而我们的dl是8位寄存器,那么答案很明显了。不能!
  4. 那到底应该如何做呢?

    这里有两个问题,类型的匹配和结果的不超界,我们可以考虑用一个16位的寄存器来做中介。将内存单元中的8位数据赋值到一个16位寄存器ax中,再将ax中的数据加到dx上,从而使两个运算对象类型匹配并且结果不会超界。

考虑完以上问题,很明显,如果是在高级语言中,这是一个很容易做的问题,一个循环就可以实现,那么在汇编中,我们也可以用循环来实现这个操作。我们可以把BX用作存储内存单元偏移地址的变量,在每次循环的时候改变BX中的值,从而实现把 ffff:0~ffff:b 12个内存单元中的数据相加。

实现如下:

assume cs:code
code segment
    start:             ;程序入口
    mov ax, 0ffffh
    mov ds, ax
    mov bx, 0       ;初始化ds:bx指向ffff:0

    mov dx, 0      ;初始化累加寄存器dx,(dx)=0

    mov cx, 12
    s:
    mov al, [bx]
    mov ah, 0
    add dx, ax
    inc bx          ;使ds:bx指向下一个内存单元
    loop s

    mov ax, 4c00h
    int 21h
code ends
end start        ;程序结束

段前缀

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

mov ax, ds:[bx]
mov ax, cs:[bx]
mov ax, ss:[bx]
mov ax, es:[bx]
mov ax, ss:[0]
mov ax, cs:[0]

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

段前缀的使用

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

分析:

  1. 0:200 ~0:20b 单元等同于 0020:0~0020:b 单元,它们描述的是同一段内存空间。
  2. 复制过程用循环实现,我们可以使用一个变量[BX]同时操作两段内存单元(使用段前缀来标识不同的段)。
  3. 将 0:200~0:20b 用 0020:0~0020:b 描述,是为了使目标单元的偏移地址和源始单元的偏移地址从同一数值0开始。

实现如下:

assume cs:code
code segment
    mov ax, 0ffffh
    mov ds, ax           ;(ds)=0ffffh

    mov ax, 0020h
    mov es, ax         ;(es)=0020h

    mov bx, 0   ;此时ds:bx指向ffff:0,es:dx指向0020:0

    mov cx, 12
    s:
    mov dl, [bx]      ;段地址默认在ds中
    mov es:[bx], dl   ;段前缀指明内存段
    inc bx
    loop s

    mov ax, 4c00h
    int 21h
code ends
end

80806汇编(5)——[BX]和Loop指令的更多相关文章

  1. 王爽汇编第五章,[bx]和loop指令

    目录 王爽汇编第五章,[bx]和loop指令 [bx]和loop指令 例子: 王爽汇编第五章,[bx]和loop指令 [bx]和loop指令 [bx]之前我们介绍寄存器的时候,已经很详细的说明过了,b ...

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

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

  3. 汇编语言-[BX]和loop指令

    汇编语言-[BX]和loop指令 [BX]指令介绍 mov ax,[bx] 功能: bx为偏移地址,段地址默认为ds.因此,上面指令作用就是将ax中的数据送入内存ds:bx处,即:((ds)*16 + ...

  4. 汇编-5.0-[BX]和loop指令

    1.要完整的描述一个内存单元,需要两种信息:1.内存单元的地址:2.内存单元的长度(类型). 2."()"表示一个寄存器或一个内存单元中的内容.如:(ax)表示ax中的内容. &q ...

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

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

  6. 小甲鱼零基础汇编语言学习笔记第五章之[BX]和loop指令

         这一章主要介绍什么是[BX]以及loop(循环)指令怎么使用,loop和[BX]又怎么样相结合,段前缀又是什么鬼,以及如何使用段前缀.   1.[BX]的概念      [BX]和[0]类似 ...

  7. [bx]和loop指令

    body, table{font-family: 微软雅黑; font-size: 13.5pt} table{border-collapse: collapse; border: solid gra ...

  8. 汇编:汇编语言实现冒泡排序(loop指令实现)

    ;=============================== ;循环程序设计 ;loop指令实现 ;冒泡排序 ;for(int i=0;i<N;i++){ ; for(int h=0;j&l ...

  9. 汇编语言-[bx]和loop指令和多个段

    5.1 [BX]和内存单元的描述 要完成描述一个内存单元,需要两种信息: 内存单元的地址: 可以用 [0] 表示一个内存单元, 0 表示单元的偏移地址,段地址默认在 ds 中: 同样也可以用 [bx] ...

随机推荐

  1. 201521123071 《JAVA程序设计》第二周学习总结

    1. 本周学习总结 在本周的学习中,主要学习了书上的String类以及Math类等知识,但是书上学到的东西只是理论,实际打起代码来的时候会学习到更多,比如在PTA上就有学习到StringBuilder ...

  2. 《MySQL必知必会》[01] 基本查询

    <MySQL必知必会>(点击查看详情) 1.写在前面的话 这本书是一本MySQL的经典入门书籍,小小的一本,也受到众多网友推荐.之前自己学习的时候是啃的清华大学出版社的计算机系列教材< ...

  3. 利用ADO让普通人用excel读取oracle数据库表的通用办法

    Ref:http://blog.csdn.net/iamlaosong/article/details/8465177 Excel通过ADO方式连接到Oracle并操作Oracle给那些编程能力不强的 ...

  4. CSDN博客新手使用方案

    CSDN博客简易使用 在CSDN上写博客,总是遇到很多问题,虽然这些问题很简单,但是对于新手来说,缺经常遇到,因此写篇博客记载. 一.CSDN的博客如何上传图片               如果有现成 ...

  5. java中判断字符串是否为数字的方法的几种方法

    1.用JAVA自带的函数 public static boolean isNumeric(String str){ for (int i = 0; i < str.length(); i++){ ...

  6. myeclipse一些快捷键 错了或者没说到补充下

    Ctrl + 1 快速修复Ctrl + D  删除当前行 Ctrl + Alt + ↓ 复制当前行到下一行(复制增加)Ctrl + Alt + ↑ 复制当前行到上一行(复制增加)Alt + ↓ 当前行 ...

  7. ioc(Inversion of Control)控制反转和DI

    ioc意味着将你设计好的交给容器控制,而不是传统在你的对象中直接控制 谁控制了谁:传统的javaSE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象:而ioc是有专门一个容 ...

  8. 使用jquery的方法和技巧2,点击多选框的jquery响应

    使用jquery来控制多选框的变化 功能描述: 1.第一层 当选中后台应用(App1)时,所有多选框都被选择. 当取消选中后台应用(App1)时,所有多选框都被取消选择. 第一层的逻辑如下: 2.第二 ...

  9. 非常有用的css使用总结

    积小流以成江海,很多东西你不总结就不是你的东西 常用css总结: /*设置字体*/ @font-face { font-family: 'myFont'; src: url('../font/myFo ...

  10. snmp4j 之 ArgumentParser

    ArgumentParser ArgumentParser命令行解析器 将数组转换成Java对象 根据预定计划选项和参数,以及相应的命令行选项联合每个对象 ArgumentParser argumen ...