80806汇编(5)——[BX]和Loop指令
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种:
- 寄存器名;
- 段寄存器名;
- 内存单元的物理地址。
其所表示的数据类型有:
- 字节;
- 字。
具体是那种类型则由寄存器名或具体的运算符决定。
2. 常量符号"idata"
用idata表示一个常量。
如用mov ax, [idata]
代表mov ax, [1]
、mov ax, [2]
等。
如用mov bx, idata
代表mov bx, 1
、mov 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寄存器中。
我们首先分析一下:
- 运算后的结果是否会超出dx能存储的范围?
ffff:0~ffff:b 内存单元中的数据是字节型的数据,范围在0~255之间,12个这样的数据相加的结果不会大于65535,是可以存储在dx寄存器中的。
- 我们能否将 ffff:0~ffff:b 中的数据直接累加到dx中?
这是比不可能的,为什么?因为数据类型不匹配,dx是16位寄存器,而 ffff:0~ffff:b 中的数据是8位的。
- 那么是否可以将其累加到dl中,并设置(dh)=0,从而实现累加到dx中?
看第一条分析,12个8字节的数据相加是有可能超过255的,而我们的dl是8位寄存器,那么答案很明显了。不能!
- 那到底应该如何做呢?
这里有两个问题,类型的匹配和结果的不超界,我们可以考虑用一个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 单元中。
分析:
- 0:200 ~0:20b 单元等同于 0020:0~0020:b 单元,它们描述的是同一段内存空间。
- 复制过程用循环实现,我们可以使用一个变量[BX]同时操作两段内存单元(使用段前缀来标识不同的段)。
- 将 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指令的更多相关文章
- 王爽汇编第五章,[bx]和loop指令
目录 王爽汇编第五章,[bx]和loop指令 [bx]和loop指令 例子: 王爽汇编第五章,[bx]和loop指令 [bx]和loop指令 [bx]之前我们介绍寄存器的时候,已经很详细的说明过了,b ...
- [汇编学习笔记][第五章[BX]和loop指令]
第五章[BX]和loop指令 前言 定义描述性符号“()”来表示一个寄存器或一个内存单元的内容,比如: (ax)表示ax中的内容,(al)表示al的内容. 约定符号ideta表示常量. 5.1 [BX ...
- 汇编语言-[BX]和loop指令
汇编语言-[BX]和loop指令 [BX]指令介绍 mov ax,[bx] 功能: bx为偏移地址,段地址默认为ds.因此,上面指令作用就是将ax中的数据送入内存ds:bx处,即:((ds)*16 + ...
- 汇编-5.0-[BX]和loop指令
1.要完整的描述一个内存单元,需要两种信息:1.内存单元的地址:2.内存单元的长度(类型). 2."()"表示一个寄存器或一个内存单元中的内容.如:(ax)表示ax中的内容. &q ...
- 第五章 [BX]和loop指令
5.1 [bx] [bx]是什么 和 [0] 有些类似,[0] 表示内存单元,它的偏移地址是 0. 例如: mov ax, [0] 内存以字节为单位:ax以字(16bit = 2Byte)为单位:al ...
- 小甲鱼零基础汇编语言学习笔记第五章之[BX]和loop指令
这一章主要介绍什么是[BX]以及loop(循环)指令怎么使用,loop和[BX]又怎么样相结合,段前缀又是什么鬼,以及如何使用段前缀. 1.[BX]的概念 [BX]和[0]类似 ...
- [bx]和loop指令
body, table{font-family: 微软雅黑; font-size: 13.5pt} table{border-collapse: collapse; border: solid gra ...
- 汇编:汇编语言实现冒泡排序(loop指令实现)
;=============================== ;循环程序设计 ;loop指令实现 ;冒泡排序 ;for(int i=0;i<N;i++){ ; for(int h=0;j&l ...
- 汇编语言-[bx]和loop指令和多个段
5.1 [BX]和内存单元的描述 要完成描述一个内存单元,需要两种信息: 内存单元的地址: 可以用 [0] 表示一个内存单元, 0 表示单元的偏移地址,段地址默认在 ds 中: 同样也可以用 [bx] ...
随机推荐
- 201521123037 《Java程序设计》第2周学习总结
1. 本周学习总结 初步学会分析使用命令提示符进行编译的命令 了解使用import引入不同包的类 学会码云与eclipse的连接 使用Array和String函数编写程序 2. 书面作业 1. 使用E ...
- 201521123096《Java程序设计》第一周学习总结
1. 本章学习总结: 对JAVA的发展有一定的了解.JAVA是一种高级语言,需要在JVM上执行.初步学会使用eclipse和NOtepad++. 2. 书面作业 Q1:为什么java程序可以跨平台运行 ...
- 201521123061 《Java程序设计》第一周学习总结
1.本周学习总结 (1) Java的来历与版本演进 最早是Sun公司绿色项目Green Project 中所撰写的Strar7应用程序的程序语言: (2)Java根据应用领域分为三大平台:Java S ...
- 201521123093 java 第十周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常与多线程相关内容. Runnable不是线程,Thread才是,必须将实现Runnable接口的类的对象放入Thread中才能在 ...
- 201521123089 《Java程序设计》第9周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常相关内容. 2. 书面作业 本次PTA作业题集异常 常用异常 题目5-11.1 截图你的提交结果(出现学号) 1.2 自己以前编 ...
- RAID磁盘阵列
什么是RAID 独立硬盘冗余阵列(RAID, Redundant Array of Independent Disks),简称磁盘阵列.其基本思想就是把多个相对便宜的硬盘组合起来,成为一个硬盘阵列组, ...
- 编译Linux-4.9.9内核流程记录
本文部分资料出自: http://www.cnblogs.com/xiaocen/p/3717993.html 首先下载代码: https://www.kernel.org/pub/linux/ker ...
- 解决在Ubuntu终端下使用cURL获取GBK格式的页面出现乱码问题
问题描述 在Ubuntu下使用终端使用cURL去拿一个GBK的页面,发现返回来的内容里面中文都是乱码 解决方法 通过iconv来处理乱码拿到的内容,进行转码,示例如下: $curl http://ww ...
- java 线程一
java基础学习总结--线程(一) 一.线程的基本概念 线程理解:线程是一个程序里面不同的执行路径 每一个分支都叫做一个线程,main()叫做主分支,也叫主线程. 程只是一个静态的概念,机器上的一个. ...
- Hadoop 一: NCDC 数据准备
Hadoop 本文介绍Hadoop- The Definitive Guide一书中的NCDC数据准备,为后面的学习构建大数据环境; 环境 3节点 Hadoop 2.7.3 集群; java vers ...