汇编语言(王爽第三版)实验4 [bx]和loop的使用

实验4  [bx]loop的使用

1.编程:向内存0:200H~0:23fH依次传送数据0~63(3FH

程序分析:

【1】内存0:200H~0:23fH空间与0020:0-0020:3f内存空间是一样的,(这个不会?oh!My God!,物理地址是唯一的,但逻辑地址组合是多种的。)

【2】因为偏移地址是连续内存单元;我们可以把偏移地址做下文章。bx寄存器存储偏移地址(通过偏移地址的间接访问内存单元,这主要是写入的内存单元)。dx寄存器作为存储中间变量的容器(源数据,常量0-63)来向内存写入。

       汇编代码如下:

assume cs:code

code segment

    mov ax,0020H

    mov ds,ax   ;内存单元的段地址写入ds寄存器

    mov bx,0    ;bx寄存器存放偏移地址,初始化为0

    mov dx,0    ;dx寄存器存储常量数值0~63

    mov cx,40H  ;这里40H==64,cx寄存器存放循环次数。也可以为64;

   

s:  mov [bx],dx ;向[bx]内存单元写入dx值

    inc bx  ;累加bx

    inc dx  ;累加dx

    loop s

 

    mov ax,4c00H

    int 21H

code ends

end

 

2. 向内存0:200H~0:23fH依次传送数据0~63(3FH),9条命令的程序的简化版本(不包括伪代码):

程序分析:

【1】内存0:200H~0:23fH空间与0020:0-0020:3f内存空间是一样的,(这个不会?oh!My God!,物理地址是唯一的,但逻辑地址组合是多种的。)为什么这样?数据0-63是64个连续的数字,0-3fH也是连续的64个编号。我们可以使用一个bx变量就把偏移地址和数字的递增都搞定了!

修改后的汇编代码如下:

assume cs:code

code segment

    mov ax,0020H

    mov ds,ax   ;ds指向0020内存段

    mov bx,0    ;bx寄存器存放偏移地址,初始化为0,也当做源数据:常量数值

    mov cx,64   ;循环次数64

   

s:  mov [bx],bx ; 向[bx]内存单元写入bx数值

    inc bx

    loop s

 

    mov ax,4c00H

    int 21H

code ends

end

实验体会:

1. bx寄存器一般用作偏移地址的存储,[bx]也就代表了段地址与[bx]组合后指向的内存单元。     为什么这样,还有一个原因就是在源程序中[xxxx]在masm编译器中当做了常量xxxx,而[bx]则没有这个问题,编译器当做是一个内存地址段的偏移地址。

2.cx寄存器在循环语句中,常作为计数器使用,loop循环语句把cx寄存器中的值作为判断是否循环的依据。

       CX寄存器在debug调试一个可执行程序时,CX的初始值为该程序的字节尺寸大小。

3.ds寄存器存放的是指向的内存单元的段地址。

4.在debug模式下,注意源程序中loop s语句的体现,直接转移到了一个地址(偏移地址)了。

5.结束debug程序,键入q,退回到dos或命令提示符状态。

6.在debug状态下,如果想要直接执行的到某个语句,可使用g命令,例如:

       g  XXXX(偏移地址)   在此之前的命令都执行了。

7.在汇编源程序中,数据不能以字母开头,前面可以加0,例如:0ff02H。

8.在debug下调试程序,遇到int 21H命令,键入p命令结束程序。

9.使用p命令可以结束loop的循环(当你遇到了loop语句的时候)。

10.在写汇编程序时,十进制和十六进制(用h、H标注)可以混用。编译器自动给你转换了。

程序运行后结果:

-d ds:0

0020:0000  00 01 02 03 04 05 06 07-08 09 0A 0B 0C 0D 0E 0F   ................

0020:0010  10 11 12 13 14 15 16 17-18 19 1A 1B 1C 1D 1E 1F   ................

0020:0020  20 21 22 23 24 25 26 27-28 29 2A 2B 2C 2D 2E 2F    !"#$%&'()*+,-./

0020:0030  30 31 32 33 34 35 36 37-38 39 3A 3B 3C 3D 3E 3F   0123456789:;<=>?

3.下面程序的功能是将mov ax,4c00H之前的指令复制到内存0:200处,补全程序,上机调试,跟踪运行结果:

程序分析:

【1】使用debug调试一个EXE文件时候,使用r命令查看寄存器状态,其中cx寄存器的值(初始值)就是该程序代码的大小(按照字节数)。我们可以通过运行debug程序来调试生成的EXE文件,前提你先将CX寄存器赋个值。

       侧面验证CX寄存器的另一个作用。

【2】cs段寄存器中存储的是指向程序代码段的段地址。此实验是将程序的代码(按字节)复制,故将cs寄存器中的指向代码的段地址赋值给ax,再通过ax寄存器赋值给ds段寄存器。(为什么不能支持从段寄存器cs直接赋值给段寄存器ds呢?回忆下,在8086CPU中,ds、ss、cs、es四个段寄存器存放的都是段地址,在CPU和我们来看。其他的寄存器一般存放的都是数据。

       这4个段寄存器支持从其他寄存器中赋值,但不允许立即数直接赋值给段寄存器。)

【3】[bx]作为偏移地址为bx的内存单元,它支持的段地址默认是存储在ds段寄存器中的。       本例中ds:[bx]指向的是存储代码段的内存单元(源内存段)。由于ds被占用了,故被写入的内存单元的段地址就没有存储的段寄存器了,es寄存器上场了,es存储了地址为0020H的段地址(目标内存段),那么同样使用[bx]偏移地址的话,必须明确的指出它的前缀,故es:[bx]就指向了内存是0200H的内存单元地址段。

实验步骤如下:

(1)首先使用debug调试该程序:假如这个可执行程序(经编译、连接无误后的)为test5.exe

debug  test5.exe  

(2)使用r命令显示寄存器状态,显示整个程序代码所占字节数。

-r

AX=0000  BX=0000  CX=001C  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000

DS=0B55  ES=0B55  SS=0B65  CS=0B65  IP=0000   NV UP EI PL NZ NA PO NC

0B65:0000 8CC8          MOV     AX,CS

这里我们发现CX= 001CH。

(3)使用u命令显示汇编指令,求出需要复制的机器码字节数。

-u cs:0000

0B65:0000 8CC8          MOV     AX,CS

0B65:0002 8ED8          MOV     DS,AX

0B65:0004 B82000        MOV     AX,0020

0B65:0007 8EC0          MOV     ES,AX

0B65:0009 BB0000        MOV     BX,0000

0B65:000C B90300        MOV     CX,0003

0B65:000F 8A07          MOV     AL,[BX]

0B65:0011 26            ES:

0B65:0012 8807          MOV     [BX],AL

0B65:0014 43            INC     BX

0B65:0015 E2F8          LOOP    000F

0B65:0017 B8004C        MOV     AX,4C00

0B65:001A CD21          INT     21

       我们发现mov ax,4cooH/int 21H它们共占用了5个字节。所以在本实验中我们需要复制的代码字节数是001CH-0005H=0017H==23个字节,故cx计数寄存器赋值为23或17H。

(4)完整的汇编代码如下:

assume cs:code

code segment

    mov ax,cs       ;将cs段地址赋值给ax

    mov ds,ax       ;用cs寄存器中的值初始化ds段寄存器,

   

    mov ax,0020H

    mov es,ax       ;es指向0020H内存段

     mov bx,0        ;偏移地址寄存器清零

    mov cx,17H      ;此处是循环次数:程序机器码的字节数,存储在CX中

 

s:  mov al,[bx]     ;将[bx]按照字节单元传送给al

    mov es:[bx],al  ;复制到es段内存中

    inc bx

    loop s

   

    mov ax,4c00H

    int 21H

code ends

end

实验结果测试:

-d 20:0

0020:0000  8C C8 8E D8 B8 20 00 8E-C0 BB 00 00 B9 17 00 8A   ..... ..........

0020:0010  07 26 88 07 43 E2 F8 00-00 00 00 00 00 00 00 00   .&..C...........

……

我们发现偏移地址从0000H~0017H存储了程序的执行代码。与程序执行代码存储的内存单元比较,我们发现一样的。

-d cs:0

0B65:0000  8C C8 8E D8 B8 20 00 8E-C0 BB 00 00 B9 17 00 8A   ..... ..........

0B65:0010  07 26 88 07 43 E2 F8 B8-00 4C CD 21 FF 06 48 91   .&..C....L.!..H.

posted @ 2017-05-21 08:43  筑基2017  阅读(2367)  评论(0编辑  收藏  举报