【汇编语言】[BX]和loop指令(一)—— 初识[BX]和loop指令
文章目录
- 前言
- 1. 概念引入
- 1.1 [bx]和内存单元的描述
- 1.1.1 示例1
- 1.1.2 示例2
- 1.1.3 示例3
- 1.1.4 示例4
- 1.2 loop
- 1.3 描述性的符号:“()”
- 1.4 约定符号idata表示常量
- 2. [BX]
- 2.1 示例1
- 2.2 示例2
- 2.3 问题
- 2.4 问题分析与解答
- 3. Loop指令
- 3.1 基本用法介绍
- 3.2 任务1:编程计算 2^2,结果存在ax中
- 3.3 任务2:编程计算 2^3
- 3.4 任务3:编程计算 2^12
- 3.5 改进后的程序
- 3.5.1 标号
- 3.5.2 loop s
- 3.5.3 循环指令的执行
- 3.6 问题一及分析与解答
- 3.7 问题二及分析与解答
- 结语
前言
📌
汇编语言是很多相关课程(如数据结构、操作系统、微机原理)的重要基础。但仅仅从课程的角度出发就太片面了,其实学习汇编语言可以深入理解计算机底层工作原理,提升代码效率,尤其在嵌入式系统和性能优化方面有重要作用。此外,它在逆向工程和安全领域不可或缺,帮助分析软件运行机制并增强漏洞修复能力。
本专栏的汇编语言学习章节主要是依据王爽老师的《汇编语言》来写的,和书中一样为了使学习的过程容易展开,我们采用以8086CPU为中央处理器的PC机来进行学习。
1. 概念引入
1.1 [bx]和内存单元的描述
[bx]是什么呢?
和[0]有些类似,[0]表示内存单元,它的偏移地址是0。比如在下面的指令中(但是注意这个是在 Debug 中使用的方式):
1.1.1 示例1
mov ax, [0]
将一个内存单元的内容送入 ax,这个内存单元的长度为2字节(字单元),存放一个字,偏移地址为0,段地址在ds中。
1.1.2 示例2
mov al, [0]
将一个内存单元的内容送入al,这个内存单元的长度为1字节(字节单元),存放一个字节,偏移地址为0,段地址在ds中。
要完整地描述一个内存单元,需要两种信息:①内存单元的地址;②内存单元的长度(类型)。
用[0]表示一个内存单元时,0表示单元的偏移地址,段地址默认在ds中,单元的长度(类型)可以由具体指令中的其他操作对象(比如说寄存器)指出。
[bx]同样也表示一个内存单元,它的偏移地址在bx中,比如下面的指令:
1.1.3 示例3
mov ax, [bx]
将一个内存单元的内容送入ax,这个内存单元的长度为2字节(字单元),存放一个字,偏移地址在bx中,段地址在ds中。
1.1.4 示例4
mov al, [bx]
将一个内存单元的内容送入 al,这个内存单元的长度为1字节(字节单元),存放一个字节,偏移地址在bx中,段地址在ds中。
1.2 loop
英文单词“loop”有循环的含义,显然这个指令和循环有关。
我们在这一章的学习中,会讲解[bx]和 loop 指令的应用、意义和相关的内容。
1.3 描述性的符号:“()”
为了描述上的简洁,在以后的内容中,我们将使用一个描述性的符号“()”来表示一个寄存器或一个内存单元中的内容。
比如:
-
(ax)表示 ax 中的内容、(al)表示 al 中的内容;
-
(20000H)表示内存20000H单元的内容(括号中的是内存单元的地址为物理地址);
-
((ds)*16+(bx))表示:ds 中的内容为 ADR1,bx中的内容为 ADR2,内存 ADR1*16+ADR2 单元的内容。也可以理解为:ds中的ADR1作为段地址,bx中的ADR2作为偏移地址,内存ADR1:ADR2 单元的内容。
❗注意,“()”中的元素可以有3种类型:
①寄存器名;②段寄存器名;③内存单元的物理地址(一个 20位数据)。
比如:
(ax)、(ds)、(al)、(cx)、(20000H)、((ds)*16+(bx))等是正确的用法;
(2000:0)、((ds):1000H)等是不正确的用法。
“(X)”所表示的数据有两种类型:①字节;②字。
是哪种类型由寄存器名或具体的运算决定,比如:
-
(al)、(bl)、(cl)等得到的数据为字节型;
-
(ds)、(ax)、(bx)等得到的数据为字型。
-
(al)=(20000H),则(20000H)得到的数据为字节型;
-
(ax)=(20000H),则(20000H)得到的数据为字型。
1.4 约定符号idata表示常量
我们在 Debug 中写过类似的指令:mov ax,[0],表示将 ds:0处的数据送入 ax中。
指令中,在“[…]”里用一个常量 0表示内存单元的偏移地址。以后,我们用 idata 表示常量。比如:
mov ax,[idata]:代表mov ax,[l]、mov ax,[2]、mov ax,[3]等mov bx,idata:代表mov bx,1、mov bx,2、mov bx,3等mov ds,idata:代表mov ds,1、mov ds,2等,它们都是非法指令。
2. [BX]
看一看下面指令的功能。
2.1 示例1
mov ax, [bx]
功能:bx中存放的数据作为一个偏移地址EA,段地址SA默认在ds中,将SA:EA处的数据送入 ax中。即:(ax)=((ds)*16+(bx))。
2.2 示例2
mov [bx], ax
功能:bx中存放的数据作为一个偏移地址EA,段地址SA默认在ds中,将ax中的数据送入内存SA:EA 处。即:((ds)*16+(bx))=(ax)。
2.3 问题
程序和内存中的情况如下图所示,写出程序执行后,21000H-21007H单元中的内容。
思考后看分析。
注意,imc bx的含义是bx中的内容加1,比如下面两条指令:
mov bx, 1
inc bx
执行后,bx=2。
2.4 问题分析与解答
(1)先看一下程序的前3条指令:
mov ax, 2000H
mov ds, ax
mov bx, 1000H
这3条指令执行后,ds=2000H,bx=1000H。
(2)接下来,第4条指令:
mov ax, [bx]
指令执行前:ds=2000H,bx=1000H,则mov ax, [bx]将把内存2000:1000处的字型数据送入ax中。该指令执行后,ax=00beH。
(3)接下来,第5、6条指令:
inc bx
inc bx
这两条指令执行前 bx=1000H,执行后bx=1002H。
(4)接下来,第7条指令:
mov [bx], ax
指令执行前:ds=2000H,bx=1002H,则mov [bx], ax将把ax中的数据送入内存2000:1002处。指令执行后,2000:1002单元的内容为BE,2000:1003单元的内容为00。
(5)接下来,第8、9条指令:
inc bx
inc bx
这两条指令执行前 bx=1002H,执行后bx=1004H。
(6)接下来,第10条指令:
mov [bx], ax
指令执行前:ds=2000H,bx=1004H,则mov [bx], ax将把ax中的数据送入内存2000:1004处。指令执行后,2000:1004单元的内容为BE,2000:1005单元的内容为00。
(7)接下来,第11条指令:
inc bx
这条指令执行前 bx=1004H,执行后bx=1005H。
(8)接下来,第12条指令:
mov [bx], al
指令执行前:ds=2000H,bx=1005H,则mov [bx], al将把al中的数据送入内存2000:1005处。指令执行后,2000:1005单元的内容为 BE。
(9)接下来,第13条指令:
inc bx
这条指令执行前 bx=1005H,执行后bx=1006H。
(10)接下来,第14条指令:
mov [bx], al
指令执行前:ds=2000H,bx=1006H,则mov [bx],al将把al中的数据送入内存 2000:1006处。指令执行后,2000:1006单元的内容为 BE。
所有程序执行后,内存中的情况如下图所示。
3. Loop指令
3.1 基本用法介绍
loop指令的格式是:loop 标号。
CPU执行loop指令的时候,要进行两步操作:
①(cx)=(cx)-1;
②判断cx中的值,不为零则转至标号处执行程序,如果为零则继续向下执行。
从上面的描述中,可以看到,cx中的值影响着loop指令的执行结果。通常(注意,我们说的是通常)我们用loop指令来实现循环功能,cx中存放循环次数。
这里讲解loop指令的功能,关于loop指令如何实现转至标号处的细节,将在后面的内容中讲解。下面我们通过一个程序来看一下loop 指令的具体应用。
3.2 任务1:编程计算 2^2,结果存在ax中
分析:设(ax)=2,可计算(ax)=(ax)*2,最后(ax)中为 2^2 的值。N*2 可用 N+N 实现,程序如下。
assume cs:codecode segmentmov ax,2add ax, axmov ax,4c00hint 2lh
code endsend
3.3 任务2:编程计算 2^3
分析:2^3=2*2*2,若设(ax)=2,可计算(ax)=(ax)*2*2,最后(ax)中为 2^3 的值。N*2可用 N+N 实现,程序如下。
assume cs:codecode segmentmov ax,2add ax, axadd ax, axmov ax,4c00hint 2lh
code endsend
3.4 任务3:编程计算 2^12
分析:2^12=2*2*2*2*2*2*2*2*2*2*2*2,若设(ax)=2,可计算(ax)=(ax)*2*2*2*2*2*2*2*2*2*2*2,最后(ax)中为 2^12 的值。N*2 可用 N+N 实现,程序如下。
assume cs:codecode segmentmov ax,2;做11次add ax, axmov ax,4c00hint 2lh
code endsend
可见,按照我们的算法,计算 2^12需要11条重复的指令 add ax,ax。我们显然不希望这样来写程序,这里,可用loop来简化我们的程序。
3.5 改进后的程序
assume cs:codecode segmentmov ax,2mov cx, 11
s: add ax, axloop smov ax,4c00hint 2lh
code endsend
下面分析一下这个程序。
3.5.1 标号
在汇编语言中,标号代表一个地址,上面的程序中有一个标号s。它实际上标识了一个地址,这个地址处有一条指令:add ax, ax。
3.5.2 loop s
CPU执行loop s
的时候,要进行两步操作:
-
(cx)=(cx)-1;
-
判断cx中的值,不为0则转至标号s所标识的地址处执行(这里的指令是add ax,ax),如果为零则执行下一条指令(下一条指令是 mov ax, 4c00h)。
3.5.3 循环指令的执行
以下3条指令
mov cx, 11
s: add ax, axloop s
执行loop s
时,首先要将(cx)减1,然后若(cx)不为0,则向前转至s处执行 add ax, ax。所以,可以利用 cx 来控制 add ax, ax 的执行次数。
下面我们详细分析一下这段程序的执行过程,从中体会如何用cx和loop s
相配合实现循环功能。
(1)执行 mov cx, 11,设置(cx)=11;
(2)执行 add ax, ax(第1次);
(3)执行 loop s
将(cx)减1,(cx)=10,(cx)不为0,所以转至s处;
(4)执行 add ax, ax(第2 次);
(5)执行 loop s
将(cx)减1,(cx)=9,(cx)不为0,所以转至s处;
(6)执行 add ax, ax(第3 次);
(7)执行 loop s
将(cx)减1,(cx)=8,(cx)不为0,所以转至s处;
(8)执行 add ax, ax(第4次);
(9)执行 loop s
将(cx)减1,(cx)=7,(cx)不为0,所以转至s处;
(10)执行 add ax, ax(第5次);
(11)执行loop s
将(cx)减1,(cx)=6,(cx)不为0,所以转至s处;
(12)执行 add ax, ax(第6次);
(13)执行 loop s
将(cx)减1,(cx)=5,(cx)不为0,所以转至s处;
(14)执行 add ax, ax(第7次);
(15)执行 loop s
将(cx)减1,(cx)=4,(cx)不为0,所以转至s处;
(16)执行 add ax, ax(第8次);
(17)执行loop s
将(cx)减1,(cx)=3,(cx)不为0,所以转至s处;
(18)执行 add ax, ax(第9次);
(19)执行 loop s
将(cx)减1,(cx)=2,(cx)不为0,所以转至s处;
(20)执行 add ax, ax(第 10 次);
(21)执行 loop s
将(cx)减1,(cx)-1,(cx)不为0,所以转至s处;
(22)执行 add ax, ax(第11次);
(23)执行loop s
将(cx)减1,(cx)=0,(cx)为0,所以向下执行。(结束循环)
从上面的过程中,我们可以总结出用cx和loop指令相配合实现循环功能的3个要点:
(1)在cx中存放循环次数;
(2)loop指令中的标号所标识地址要在前面;
(3)要循环执行的程序段,要写在标号和loop 指令的中间。
用cx和loop指令相配合实现循环功能的程序框架如下。
mov cx, 循环次数
s:循环执行的程序段loop s
3.6 问题一及分析与解答
编程,用加法计算123*236,结果存在ax中。思考后看分析。
分析:
可用循环完成,将123加236 次。可先设(ax)=0,然后循环做236次(ax)=(ax)+123
程序如下。
程序:
assume cs:codecode segmentmov ax, 0mov cx, 236
s: add ax, 123loop smov ax,4c00hint 2lh
code endsend
3.7 问题二及分析与解答
改进问题一答案的程序,提高123*236的计算速度。思考后看分析。
分析:
之前的程序做了236次加法,我们可以将236加123次。可先设(ax)=0,然后循环做123 次(ax)=(ax)+236,这样可以用123次加法实现相同的功能。
结语
今天的分享到这里就结束啦!如果觉得文章还不错的话,可以三连支持一下。
也可以点点关注,避免以后找不到我哦!
Crossoads主页还有很多有趣的文章,欢迎小伙伴们前去点评,您的支持就是作者前进的动力!