汇编语言(王爽第三版)检测点:9

检测点:9.1

(1)

assume cs:code

data segment

    ???????

data ends

code segment

start:  mov ax,data

        mov ds,ax

        mov bx,0

        jmp word ptr [bx+1]

       

        mov ax,4c00H

        int 21H

code ends

end start

       若要使程序中jmp指令执行后,cs:ip指向程序的第一条指令,在data段中应定义哪些数据?

程序分析:

       1) 这个指令jmp word ptr [bx+1]是一个段内近转移,它只是修改了ip的值。它的转移地址在内存中。明确:[bx+1]在此例子中是只的data段的第二个字节。

       2)我们发现ds:bx指向了data段,word ptr [bx+1]指向的是data段中的第二个字节开始的字单元,也就是说它所指向的该字单元的内容。这个内容就是jmp跳转的偏移地址。

       3)word ptr [bx+1]指的是一个字单元,也就是说是2个字节,也就是说在data段中是第2和第3个字节,如果jmp转移到程序第一条指令,也就是说ip的值应为:00 00即可;我们要保证这二个字节的值是00 00就行。

       4)要想jmp跳转到start标号处,它的ip值是offset start即可(在汇编语言层面我们也不必关心它们代表的具体ip值是多少);也就是说:(ds:[bx+1])==offset start,那么在data段中定义的第二个字必须是offset start。至于offset start具体代表的二进制码是什么,那是编译器的事情。

       5)第一个字节,你随意定义成什么都行。

       这个结果是多个:

    dw 00xxH, offset start          ;xx代表任意数值(一个字节的)

       讲解:此时借用的是00xxH的高位字节值,00

    db x,0,0                        ;x代表任意数值(一个字节的)

    dd 0                            ;2个字的内存单元,00 00 00 00

db 3 dup (0)

dw 2 dup (0)

dd 0

       简单来说就是,只要ds:[bx+1]起始地址的两个字节为0就可以了

      

       (2)程序如下:

assume cs:code

data segment

    dd 12345678H

data ends

code segment

start:  mov ax,data

        mov ds,ax

        mov bx,0

        mov [bx], offset start

        mov [bx+2], code

        jmp dword ptr ds:[0]

       

        mov ax,4c00H

        int 21H

code ends

end start

       补全程序,使cs:ip指向程序的第一条指令。

       程序分析:

              1)在data段中定义了一个双字的值,占用4个字节,内存中是12 34 56 78

        2)jmp dword ptr ds:[0]代表的含义是,此指令是段间转移的指令,cs和ip是存储在一个双字的单元中,其中高16位存储的是cs值,低16位存储的是ip值。

              3) [bx]代表了低16位的值==ip。[bx+2]代表了高16位的值==cs。

              4)也就是说保证data段中前2个字节是ip的值,第3,4字节是cs的值就可以。

              5)答案也就多了。

        [bx]==ip

        offset start

        ptr word 0

        0000H

        bx             

        [bx+2] ==cs

        cs

        code

       (3)用Debug查看内存,结果如下:

2000:1000 BE 00 06 00 00 00 ......

则此时,CPU执行指令:

mov ax,2000h

mov es,ax

jmp dword ptr es:[1000h]

程序分析:

1)通过上面二条指令,es指向了段地址是2000H的内存段。

2)jmp dword ptr es:[1000h]指令的含义:是一个段间转移指令,指令的转移地址在内存中,该内存单元是一个双字单元(32位的单元),也就是说在1000H地址开始,低16位存储的是ip的值,高16位存储的是cs的值。

3)我们在debug内存存储显示中,不难发现,低16位是BE 00,也就是它的值是00BE。高16位是0600,也就是它的值是0006H,得出结论:(cs)= 0006H ,(ip)= 00BEH

 

检测点9.2

       补全编程,利用jcxz指令,实现在内存2000H段中查找第一个值为0的字节,找到后,将它的偏移地址存储在dx中。

assume cs:code

code segment

 start: mov ax,2000h

        mov ds,ax

        mov bx,0

     s:               

                     

                     

                     

        jmp short s

    ok: mov dx,bx

        mov ax ,4c00h

        int 21h

code ends

end start

       程序分析:

       标号s前面是将ds:bx指向了段地址为2000H的内存段。s标号到jmp short s是一个循环(死循环,除非有跳出语句)。

       这里我们需要jcxz有条件转移语句来实现循环的跳出,jcxz的逻辑表达式只有一个就是(cx)=0,想法将cx的内容赋值为ds:bx,也就是说从ds:[0]开始,逐个字节的将单元内容赋值给cx,然后执行jcxz语句。

       由于是逐个字节的比较,bx的偏移量应该是以字节为单元。我们使用的cx寄存器是16位的,我们只需要低8位的cl寄存器就可以了。为了保证ch为0,首先必须置零。它们组合在一起就是cx的整体值(dh+dl)

       需填充的第一行:mov cl,[bx]         ;将2000段内存逐个字节赋值给cl

                     第二行:mov ch, 0           ;保证高8位为0          

                     第三行:jcxz ok                  ;判断cx值,如果cx=0,跳转到ok标号

                     第四行:inc bx                   ;cx!=0,继续执行jcxz后面的语句。递增bx,

       完整的程序是:

assume cs:code

code segment

 start: mov ax,2000h

        mov ds,ax

        mov bx,0

     s: mov cl[bx]

         mov ch 0 

        jcxz ok   

        inc bx    

        jmp short s

    ok: mov dx,bx

        mov ax ,4c00h

        int 21h

code ends

end start

 

检测点9.3

       补全编程,利用loop指令,实现在内存2000H段中查找第一个值为0的字节,找到后,将它的偏移地址存储在dx中。

assume cs:code

code segment

start:  mov ax,2000h

        mov ds,ax

        mov bx,0

      s:mov cl,[bx]

        mov ch,0

        inc cx

        inc bx

        loop s

     ok:dec bx

        mov dx,bx

        mov ax,4c00h

        int 21h

code ends

end start

       程序分析:

       1)保证这个loop循环的动力是:cx!=0,首先搞清这点。

       2)  如果ds:[0]=0情况下。如果我们使用jcxz指令,只有这种情况满足条件,第一个字节为0.故不能使用jcxz指令。

       3)理解loop指令的动作,首先是(cx)=(cx)-1.然后才是跳转到标号执行。

       4)添加inc cx指令

       如果第一个字节是0情况,inc cx导致(cx)=1,执行到loop指令时,首先(cx)=(cx)-1,导致(cx)=0,loop顺序执行下面的指令(也就是标号ok的指令)。

       如果第一个字节非0情况,inc cx导致(cx)>1,执行到loop指令是,首先(cx)=(cx)-1,导致(cx)> 0(不为0),loop跳转到s标号处执行代码。

       5)答案:inc cx

posted @ 2017-05-21 09:04  筑基2017  阅读(2217)  评论(0编辑  收藏  举报