第13章
检测点13.1
(1)在上面的内容中,我们用7ch中断例程实现loop的功能,则上面的7ch中断例程所能进行的最大转移位移是多少?
解析: 我们知道转移位移是存放在BX中的,而BX是一个16位的寄存器,所以最大的转移位移是:-32768~32767。
(2).用7ch中断例程完成jmp near ptr s指令的功能,用bx向中断例程传送转移位移。
应用举例:在屏幕的第12行,显示data段中以0结尾的字符串。
程序如下:
assume cs:code
data segment
db 'conversation',0
data ends
code segment
start:;7ch中断处理程序安装
mov ax,cs
mov ds,ax ;ds指向当前程序的段地址
mov si,offset lp ;将中断处理程序的偏移地址放入si
mov ax,0
mov es,ax ;es指向内存单元0处
mov di,200h ;将偏移地址为200h的内存单元地址放入di
mov cx,offset lpend-offset lp ;计算中断处理程序的空间
cld ;设置正方向
rep movsb ;安装中断处理程序
mov ax,0
mov es,ax ;es指向中断向量表
mov word ptr es:[7ch*4],200h ;将中断处理程序的入口地址安装到中断向量表中(偏移地址)
mov word ptr es:[7ch*4+2],0 ;将中断处理程序的入口地址安装到中断向量表中(段地址)
mov ax,data
mov ds,ax ;ds指向数据段(字符串)
mov si,0 ;后面使用si访问字符串
mov ax,0b800h
mov es,ax ;es指向显存空间
mov di,12*160 ;后面使用di访问显存空间
s:cmp byte ptr [si],0 ;和0进行比较
je ok ;等于0则转移
mov al,[si] ;将单个字符取出放入al中
mov es:[di],al ;将al中的内容写入显存空间
inc si ;si+1指向下一个字符
add di,2 ;di+2指向下一个显存空间
mov bx,offset s-offset ok
int 7ch
ok:mov ax,4c00h
int 21h
;中断处理程序
lp:push bp ;将bp入栈
mov bp,sp ;此时bp中为栈顶的偏移地址
add [bp+2],bx ;[bp+2]中为ok的偏移地址,加上bx中的转移位移即为s的偏移地址
lpret:pop bp
iret
lpend:nop
code ends
end start
将上面的程序在DOS中运行后效果如下:
检测点13.2
判断下面说法的正误:
(1).我们可以编程改变FFFF:0处的指令,使得CPU不去执行BIOS中的硬件系统检测和初始化程序。
解析: 这一点是错误的。我们知道FFFF:0处存放的是一条跳转指令,是只读的,无法改变。
(2).int 19h中断例程,可以由DOS提供。
解析: 这一点也是错误的。硬件系统检测和初始化完成后,调用int 19h进行操作系统的引导。从此将计算机交由操作系统控制,引导DOS启动。
实验13 编写、应用中断例程
(1).编写并安装int 7ch中断例程,功能为显示一个用0结束的字符串,中断例程安装在0:200处。
参数:(dh)=行号,(dl)=列号,(cl)=颜色,ds:si指向字符串首地址
以上中断例程安装成功后,对下面的程序进行单步跟踪,尤其注意观察int、iret指令执行前后cs、ip和栈中的状态。
程序如下:
assume cs:code
data segment
db "welcome to masm!",0
data ends
code segment
start:;7ch中断处理程序安装
mov ax,cs
mov ds,ax ;ds指向当前程序的段地址
mov si,offset lp ;将中断处理程序的偏移地址放入si
mov ax,0
mov es,ax ;es指向内存单元0处
mov di,200h ;将偏移地址为200h的内存单元地址放入di
mov cx,offset lpend-offset lp ;计算中断处理程序的空间
cld ;设置正方向
rep movsb ;安装中断处理程序
mov ax,0
mov es,ax ;es指向中断向量表
mov word ptr es:[7ch*4],200h ;将中断处理程序的入口地址安装到中断向量表中(偏移地址)
mov word ptr es:[7ch*4+2],0 ;将中断处理程序的入口地址安装到中断向量表中(段地址)
s:mov dh,10 ;dh中存放行号(第10行)
mov dl,10 ;dl中存放列号(第10列)
mov cl,2 ;cl中存放颜色属性
mov di,0
mov al,160 ;1行160个字节
mul dh ;计算行偏移地址
add di,ax ;放入di中
mov al,2 ;1列2个字节
mul dl ;计算列偏移地址
add di,ax ;放入di中
mov ax,0b800h
mov es,ax ;es指向显存空间
mov ax,data
mov ds,ax ;ds指向数据段(字符串)
mov si,0 ;使用si访问字符串
mov al,cl ;将颜色属性保存到al中
int 7ch ;调用中断程序
mov ax,4c00h
int 21h
lp:mov ch,0 ;将ch清零
mov cl,ds:[si] ;将单个字符取出放入cl中
jcxz lpret ;为0则转移
mov ch,al ;将颜色属性放入ch
mov es:[di],cx ;将单个字符数据写入显存空间
inc si ;si+1指向下一个字符
add di,2 ;di+2指向下一个显存空间
jmp near ptr lp
lpret:iret
lpend:nop
code ends
end start
将上面的程序在DOS中运行后效果如下:
(2).编写并安装int 7ch中断例程,功能为完成loop指令的功能。
参数:(cx)=循环次数,(bx)=位移
以上中断例程安装成功后,对下面的程序进行单步跟踪,尤其注意观察int、ret指令执行前后cs、ip和栈中的状态。
在屏幕中间显示80个’!'。
程序如下:
assume cs:code
code segment
start:;7ch中断处理程序安装
mov ax,cs
mov ds,ax ;ds指向当前程序的段地址
mov si,offset lp ;将中断处理程序的偏移地址放入si
mov ax,0
mov es,ax ;es指向内存单元0处
mov di,200h ;将偏移地址为200h的内存单元地址放入di
mov cx,offset lpend-offset lp ;计算中断处理程序的空间
cld ;设置正方向
rep movsb ;安装中断处理程序
mov ax,0
mov es,ax ;es指向中断向量表
mov word ptr es:[7ch*4],200h ;将中断处理程序的入口地址安装到中断向量表中(偏移地址)
mov word ptr es:[7ch*4+2],0 ;将中断处理程序的入口地址安装到中断向量表中(段地址)
mov ax,0b800h
mov es,ax ;es指向显存空间
mov di,160*12 ;设置显存空间的偏移地址
mov bx,offset s-offset se ;计算位移
mov cx,80 ;一个80个字符
s:mov byte ptr es:[di],'!' ;将单个字符放入写入显存空间
add di,2 ;di+2指向下一个显存空间
int 7ch
se:nop
mov ax,4c00h
int 21h
;中断处理程序
lp:push bp
mov bp,sp
dec cx
jcxz lpret
add [bp+2],bx
lpret:pop bp
iret
lpend:nop
code ends
end start
将上面的程序在DOS中运行后效果如下:
(3).下面的程序,分别在屏幕的第2、4、6、8行显示4句英文诗,补全程序。
程序如下:
assume cs:code
code segment
s1: db 'Good,better,bets,','$'
s2: db 'Never let it rest,','$'
s3: db 'Till good is better,','$'
s4: db 'And better,best.','$'
s: dw offset s1,offset s2,offset s3,offset s4
row: db 2,4,6,8
start:mov ax,cs
mov ds,ax
mov bx,offset s
mov si,offset row
mov cx,4
ok:mov bh,0 ;第0页
mov dh,ds:[si] ;行号
mov dl,0 ;列号
mov ah,2 ;光标
int 10h
mov dx,ds:[bx] ;指向字符串首地址
mov ah,9 ;在光标位置显示字符
int 21h
inc si
add bx,2
loop ok
mov ax,4c00h
int 21h
code ends
end start
将上面的程序在DOS中运行后效果如下: