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. 201521123072《java程序设计》第十周学习总结

    201521123072<java程序设计>第十周学习总结 1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常与多线程相关内容. 2. 书面作业 本次PTA作业题集异 ...

  2. 201521123121 《Java程序设计》第13周学习总结

    1. 本周学习总结 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 1.两类传输协议:TCP:UDP TCP/IP协议的名称中只有TCP这个协议名,但是在TCP/IP的传输层 ...

  3. JAVA课程设计-学生信息管理系统(个人博客)

    1. 团队课程设计博客链接 http://www.cnblogs.com/Min21/p/7064093.html 2.个人负责模块或任务说明 负责person类的编写,建立person对象, 完成M ...

  4. 前端里移动端到底比pc端多哪些知识?

    端里移动端到底比pc端多哪些知识,为啥面试时好多公司都问h5水平如何? 我做过几年的web前端开发,就简单谈谈自己的感受吧.首先来看看PC端和移动端在前端开发上的一些区别:(1)PC考虑的是浏览器兼容 ...

  5. PHP命令注入笔记

    一.PHP命令注入介绍 在学习php相关的攻击时,遇到了Command Injection,即命令注入攻击,是指这样一种攻击手段,黑客通过把HTML代码输入一个输入机制(例如缺乏有效验证限制的表格域) ...

  6. String类的构造方法(2)

    写了常见的几个而已. 1:new 一个String类的时候系统会自动传一个空构造 public String(); 注意: 当对象初始化是 null时 和 对象是 "" 时,两者是 ...

  7. 如何解决conda install:command not found问题

    每次运行conda相关代码之前先做一遍source ~/.bashrc.即可

  8. Java Byte取值范围

    Java Byte 的取值范围大家都知道(-128 ~ 127),那么-128 和 127 这两个数是怎么计算的呢? #大学知识回顾: 概念:负数的补码是该 数 绝 对 值 的 原 码 按 位 取 反 ...

  9. js中set和get的用法

    get 语句作为函数绑定在对象的属性上,当访问该属性时调用该函数. set 语法可以将一个函数绑定在当前对象的指定属性上,当那个属性被赋值时,你所绑定的函数就会被调用. eg: var log = [ ...

  10. HashMap的源码分析(一)

    1.hashMap的关键值 DEFAULT_INITIAL_CAPACITY:默认初始容量16,∈(0,1<<30),实际大小为2的整数次幂: DEFAULT_LOAD_FACTOR:默认 ...