工学1号馆

home

[bx]和loop指令

Wu Yudong    September 13, 2016     Assembly   609   

[bx]和内存单元的描述

我们要完整地描述一个内存单元,需要两种信息:

(1)内存单元的地址;

(2)内存单元的长度(类型)。

我们用[0]表示一个内存单元时,0 表示单元的偏移地址,段地址默认在ds中,单元的长度(类型)可以由具体指令中的其他操作对象(比如说寄存器)指出。

[bx]同样也表示一个内存单元,它的偏移地址在bx中,比如下面的指令:

mov ax,[bx]

mov al,[bx]

为了描述上的简洁,在以后的文章中,使用一个描述性的符号 “() ”来表示一个寄存器或一个内存单元中的内容。这种方法主要为了叙述的方便,有点类似C语言的*运算的意味

我们看一下(X)的应用,比如:

(1)ax中的内容为0010H,我们可以这样来描述:(ax)=0010H;

(2)2000:1000 处的内容为0010H,我们可以这样来描述:(21000H)=0010H;

(3)对于mov ax,[2]的功能,我们可以这样来描述:(ax)=((ds)*16+2);

(4)对于mov [2],ax 的功能,我们可以这样来描述:((ds)*16+2)=(ax);

(5)对于 add ax,2 的功能,我们可以这样来描述:(ax)=(ax)+2;

(6)对于add ax,bx的功能,我们可以这样来描述:(ax)=(ax)+(bx);

(7)对于push ax的功能,我们可以这样来描述:
(sp) = (sp)-2

((ss)*16+(sp))=(ax)

注意:“()”中的元素可以有3种类型:寄存器名、段寄存器名、内存单元的物理地址

约定符号idata表示常量

比如:

mov ax,[idata]就代表mov ax,[1]、mov ax,[2]、mov ax,[3]等。

mov bx,idata就代表mov bx,l、mov bx,2、mov bx,3等。

mov ds,idata就代表mov ds,1、mov ds,2等,它们都是非法指令。

[BX]

我们看一看下面指令的功能:

mov ax,[bx]

功能:bx 中存放的数据作为一个偏移地址EA ,段地址SA 默认在ds 中,将SA:EA处的数据送入ax中。

即: (ax)=(ds *16 +(bx));

mov [bx],ax

功能:bx中存放的数据作为一个偏移地址EA,段地址SA默认在ds中,将ax中的数据送入内存SA:EA处。

即:(ds *16 +(bx))  =  (ax)。

来实践一下

mov ax,2000H
mov ds,ax
mov bx,1000H
mov ax,[bx]
inc bx
inc bx
mov [bx],ax
inc bx
inc bx
mov [bx],ax
inc bx
mov [bx],al
inc bx
mov [bx],al

跟踪执行上面的代码:

首先执行-debug 2.exe

-r

AX=FFFF  BX=0000 CX=001D  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000

DS=075A  ES=075A  SS=0769  CS=076A  IP=0000  NV  UP  EI  NZ  NA  PO  NC

076A:0000  B80020        MOV    AX,2000

-t

AX=2000  BX=0000 CX=001D  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000

DS=075A  ES=075A  SS=0769  CS=076A  IP=0003  NV  UP  EI  NZ  NA  PO  NC

076A:0003  8ED8        MOV    DS,AX

-t

AX=2000  BX=0000 CX=001D  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000

DS=2000  ES=075A  SS=0769  CS=076A  IP=0005  NV  UP  EI  NZ  NA  PO  NC

076A:0005  BB0010        MOV    BX,1000

-t

AX=2000  BX=1000 CX=001D  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000

DS=2000  ES=075A  SS=0769  CS=076A  IP=0008  NV  UP  EI  NZ  NA  PO  NC

076A:0008  8B07        MOV    AX,[BX]                                            DS:1000=0000

这三条指令执行后

ds=2000H,  bx=1000H;

-t

AX=0000  BX=1000 CX=001D  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000

DS=2000  ES=075A  SS=0769  CS=076A  IP=000A  NV  UP  EI  NZ  NA  PO  NC

076A:000A   43            INC     BX

说明:mov ax,[bx] 将内存2000:1000处的数据送入ax中,而DS:1000=0000,执行之后ax=0000H

-t

AX=0000  BX=1001  CX=001D  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000

DS=2000  ES=075A  SS=0769  CS=076A  IP=000B   NV  UP  EI  NZ  NA  PO  NC

076A:000B   43            INC     BX

-t

AX=0000  BX=1002  CX=001D  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000

DS=2000  ES=075A  SS=0769  CS=076A  IP=000C   NV  UP  EI  NZ  NA  PO  NC

076A:000C   8907            MOV     [BX],AX                                                 DS:1002=0000

连续执行inc bx  inc bx,bx=1001H,bx=1002H

-t

AX=0000  BX=1004  CX=001D  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000

DS=2000  ES=075A  SS=0769  CS=076A  IP=000E   NV  UP  EI  NZ  NA  PO  NC

076A:000E   43             INC     BX

执行前,DS=2000H,BX=1002,执行MOV     [BX],AX 即是将AX中的数据传到2000:1002处

接下来连续执行inc bx  inc bx,bx=1003H,bx=1004H

-t

AX=0000  BX=1004  CX=001D  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000

DS=2000  ES=075A  SS=0769  CS=076A  IP=0010   NV  UP  EI  NZ  NA  PO  NC

076A:0010   8907            MOV     [BX],AX                                                 DS:1004=0000

-t

AX=0000  BX=1004  CX=001D  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000

DS=2000  ES=075A  SS=0769  CS=076A  IP=0012   NV  UP  EI  NZ  NA  PO  NC

076A:0012   43                  INC     BX

执行前,DS=2000H,BX=1004,执行MOV     [BX],AX 即是将AX中的数据传到2000:1004处

接下来连续执行inc bx,bx=1005H

-t

AX=0000  BX=1005  CX=001D  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000

DS=2000  ES=075A  SS=0769  CS=076A  IP=0013   NV  UP  EI  NZ  NA  PO  NC

076A:0013   8807            MOV     [BX],AL                                                 DS:1005=00

执行前,DS=2000H,BX=1005,执行MOV     [BX],AX 即是将AL中的数据00传到2000:1005处

接下来连续执行inc bx,bx=1006H

后面的一点指令省略,原理都差不多


LOOP指令

指令的格式是:loop 标号,CPU 执行loop指令的时候,要进行两步操作:

① (cx)=(cx)-1;

② 判断cx中的值,不为零则转至标号处执行程序,如果为零则向下执行。

从上面的描述中,我们可以看到,cx中的值影响着loop指令的执行结果。

通常我们用loop指令来实现循环功能,cx 中存放循环次数。

任务1:编程计算2^12,结果存放在ax中。

分析: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:code
code segment
    mov ax,2
    mov cx,11
s:  add ax,ax
    loop s
    mov ax,4c00h
    int 21h
code ends
end

程序分析:

(1)标号
在汇编语言中,标号代表一个地址,此程序中有一个标号s 。它实际上标识了一个地址,这个地址处有一条指令:add ax,ax。

(2)loop s

CPU 执行loop s的时候,要进行两步操作:

① (cx)=(cx)-1;

② 判断cx 中的值,不为0 则转至标号s 所标识的地址处执行(这里的指令是“add ax,ax),如果为零则执行下一条指令(下一条指令是mov ax,4c00h)。

(3)以下三条指令

mov cx,11

s: ddd ax,ax

loop s

执行loop s时,首先要将(cx)减1,然后若(cx)不为0,则向前转至s处执行add ax,ax。所以,我们可以利用cx来控制

add ax,ax的执行次数。

最后结果,ax=1000H

如果文章对您有帮助,欢迎点击下方按钮打赏作者

Comments

No comments yet.
To verify that you are human, please fill in "七"(required)