第九章 检测点9.1、2、3解析
检测点9.1
(1)程序如下。
若要使程序中的jmp指令执行后,CS:IP指向程序的第一条指令,在data段中应该定义哪些数据?
**解析:**从上面的程序中,我们可以看到在执行完前3条指令后,DS寄存器中存放的是数据段data的段地址,BX寄存器中存放的是数据段data的偏移地址0,现在jmp这条指令是要跳转到以偏移地址为BX+1的内存单元中存放的数据为偏移地址的目的地,既然需要使CS:IP指向程序的第一条指令,那么只需要使IP指向0即可,所以需要在数据段中定义如下数据:db 0,0,0。
(2)程序如下。
补全程序,使jmp指令执行后,CS:IP指向程序的第一条指令。
解析:
assume cs:code
data segment
dd 12345678H
data ends
code segment
start:mov ax,data ;将数据段的段地址放入AX寄存器中
mov ds,ax ;将AX寄存器中的内容放入DS寄存器中,即数据段的段地址
mov bx,0 ;将0送入BX寄存器中
mov [bx],bx ;将BX寄存器中的内容送入偏移地址为BX中内容的内存单元,即将数据0送入偏移地址为0的内存单元中,注意这里是字传输
mov [bx+2],cs ;将CS寄存器中的内容送入偏移地址为bx+2的内存单元中,即代码段的段地址,此时数据段中的数据已经由12345678H变成了程序第一条指令的地址
jmp dword ptr ds:[0] ;跳转到第一条指令的地址
code ends
end start
注意高地址处的字是转移的目的段地址,低地址处是转移的目的偏移地址。
将上面程序在DOS中运行后如下:
程序加载后使用R命令查看寄存器中内容,我们可以看到CS:IP = 076B:0000,即第一条指令的地址。另外我们可以看到数据段的段地址为076A。
使用D命令查看内存单元中的数据可以看到此时数据还是12345678H。
下面继续执行程序到jmp指令之前,我们可以使用D命令再次查看内存单元中的数据,此时已经变成了第一条指令的地址076B:0000。
执行jmp指令后,我们可以看到此时CS:IP又变成了076B:0000,即此时已经指向了第一条指令。
(3).用Debug查看内存,结果如下:
2000:1000 BE 00 06 00 00 00 …
则此时,CPU执行指令:
mov ax,2000H
mov es,ax
jmp dword ptr es:[1000H]
后,(CS)=?,(IP)= ?
解析:从上面程序中,首先将2000H放入了AX寄存器中,即内存单元的段地址,然后放入了ES中,此时ES中的数据即为2000H,然后使用跳转指令,跳转的地址存放在内存单元2000:1000中,注意此时是dword型,高地址存放段地址0006,低地址处存放偏移地址00BE。
检测点9.2
补全编程,利用jcxz指令,实现在内存2000H段中查找第一个值为0的字节,找到后,将它的偏移地址存储在dx中。
解析:
assume cs:code
code segment
start:mov ax,2000H ;将2000H放入AX寄存器中
mov ds,ax ;将AX寄存器中的内容放入DS寄存器中,此时DS中存放的即为内存单元的段地址2000H
mov bx,0 ;将0送入BX寄存器中
s:mov cl,[bx] ;将偏移地址为[BX]内存单元中的数据放入CX低八位寄存器中(注意是字节)
mov ch,0 ;清除CX寄存器的高八位
jcxz ok ;判断CX中是否为0,为0则跳转到OK执行
inc bx ;不为0,则继续执行,BX加1
jmp short s ;跳转到S重新查找
ok:mov dx,bx ;如果CX中为0了,则说明找到了值为0的字节,此时将偏移地址BX存放在DX中
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 ;如果查找到为0的字节,则将CX加1,后面执行loop时,先将CX减1,即为0,向下继续执行
inc bx
loop s
ok:dec bx
mov dx,bx
mov ax,4c00h
int 21h
code ends
end start