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. 201521123067 《Java程序设计》第12周学习总结

    201521123067 <Java程序设计>第12周学习总结 1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多流与文件相关内容. 2. 书面作业 将Student对 ...

  2. Scrapy爬虫框架解析

    Scrapy框架解析 Scrapy框架大致包括以下几个组件:Scrapy Engine.Spiders.Scheduler.Item Pipeline.Downloader: 组件 Scrapy En ...

  3. Mysql中设置默认时间为当前值

    1.直接在创建表时添加该列并声明默认值,如下: CREATE TABLE `table1` ( `id` ) NOT NULL, `createtime` timestamp NULL default ...

  4. 二叉树终极教程--BinarySearchTree

    BinarySearchTreeMap 的 实现 public interface Map<K extends Comparable<K>, V> { void put(K k ...

  5. 使用cocos2d脚本生成lua绑定

    这几天要老大要求把DragonBones移到cocos2dx 3.0 里边,并且绑定lua使用接口.因为刚学lua,使用的引擎也刚从2.2改为3.0,各种不熟悉,折腾了好几天才弄完,有空了总结一下 这 ...

  6. JS中关于数组的内容

      前  言 LIUWE 在网站制作过程中,数组可以说是起着举足轻重的地位.今天就给大家介绍一下数组的一些相关内容.例如:如何声明一个数组和在网站制作过程中我们常用的一些数组的方法.介绍的不好还请多多 ...

  7. Angular2响应式表单

    本文将半翻译半总结的讲讲ng2官网的另一个未翻译高级教程页面. 原文地址. 文章目的是使用ng2提供的响应式表单技术快速搭出功能完善丰富的界面表单组件. 响应式表单是一项响应式风格的ng2技术,本文将 ...

  8. 用wrk测试nginx/ndoejs/golang

    sudo taskset -c ./wrk -c1 -t1 -d30 http://localhost/hello wrk+nginx(helloworld module) sudo taskset ...

  9. websocket的理解及实例应用

    websocket协议是HTML5提出的一个新的规范,主要用于实现服务器及时推送信息给客户端的功能. websocket实现是基于HTTP协议的部分握手功能,但是websocket仅仅握手一次即可进行 ...

  10. C#ZIP根据路径读取压缩包内文件数量

    /// <summary> /// 根据压缩包路径读取此压缩包内文件个数 /// </summary> /// <param name="strAimPath& ...