(二十二)《汇编语言(王爽)》 | 检测点 13.1、检测点 13.2


1. 预备知识

首先介绍用 7ch 中断例程完成 loop 指令的循环功能。loop 的执行需要用到两个信息,循环次数和到标号的转移位移。如循环代码:

	mov ax,1
	mov cx,4
s:
	add ax,ax
	loop s

上述 loop s 指令的具体功能是:执行到 loop s 时,寄存器 CX 的值减一,如果为零则跳出循环执行后续程序;如果不为零,则 CS:IP 的值设置为标号 s 的地址继续执行循环体。在程序执行过程中,CS:IP 的值共设置 (cx) 次。

对于 int 7ch 中断例程,中断向量表的第 7ch 个表项为对应中断处理程序的入口地址。由 实验12 的内容,得到安装程序:

assume cs:code
code segment
start:
	mov ax,0
	mov es,ax
	mov di,200h
	mov ax,cs
	mov ds,ax 
	mov si,offset lp  
	mov cx,offset lpend-offset lp 	;待安装程序的长度
	cld								;设置传输方向为正
	rep movsb
	mov ax,0
	mov es,ax 
	mov word ptr es:[7ch*4],200h	;低地址写入偏移地址
	mov word ptr es:[7ch*4+2],0		;高地址写入段地址
	mov ax,4c00h 
	int 21h
lp:
	;待完成的中断处理程序
lpend:
	nop
code ends 
end start

如在屏幕中间显示 80 个绿色 ! 的字符的程序。首先,循环次数存放在寄存器 CX 中;对于转移位移,通过两标号间的位移得到,存放在寄存器 BX 中。得到调用代码:

assume cs:code
code segment
start:
	mov ax,0b800h
	mov es,ax 					;段寄存器ES指向显示区域
	mov di,160*12				;变址寄存器DI指向显示区域的中部
	mov bx,offset s-offset se	;设置从标号se到标号s的转移位移
	mov cx,80					;存放循环次数
s:
	mov byte ptr es:[di],'!'	;将'!'写入显示缓冲区
	mov byte ptr es:[di+1],2h	;字体颜色为绿色
	add di,2					;每次偏移两个字节
	int 7ch						;调用7ch中断例程
se:
	mov ax,4c00h
	int 21h
code ends 
end start

int 7ch 引用中断后,进入 7ch 中断例程。在中断过程中,当前的标志寄存器、CS、IP 都要入栈。此时,入栈的 CS:IP为调用程序的地址,即标号 s 的段地址为 CS、编号 se 的偏移地址为 IP。

又前面寄存器 BX 存放了标号 se 到标号 s 的转移位移,所以标号 s 的偏移地址等于 (bx) 加上标号 se 的偏移地址。以此,将 CS:IP 的内容设置为标号 s 的段地址和偏移地址即可实现跳转。

寄存器 BP 称为指针寄存器,和段寄存器 SS 配合使用访问栈中数据。由于在中断处理程序中后续会使用寄存器 BP,首先将其入栈。现考虑栈中的数据存放情况,首先栈顶是 se 的偏移地址,然后是 s 的段地址,然后是标志寄存器。

栈顶偏移地址存放在 SP 中,从栈顶往下数第二个为 se 的偏移地址,所以 se 的偏移地址可表示为 (sp)+2,即标号 s 的偏移地址可表示为 ss:((sp)+2)+(bx)。此时,栈中 se 的偏移地址变为 s 的偏移地址。后续执行 iret 恢复现场后,CS:IP 自动指向标号 s 的地址。则中断处理程序为:

lp:
	push bp
	mov bp,sp
	dec cx
	jcxz lpret	 	;如果(cx)等于0,则跳转到lpret,此时IP内容不变,执行标号se的代码
	add [bp+2],bx	;否则,栈中se的偏移地址变为s的偏移地址,IP内容改变,执行标号s的代码
lpret:
	pop bp
	iret

得到 int7ch 的安装程序如下:

assume cs:code
code segment
start:
	mov ax,0
	mov es,ax
	mov di,200h
	mov ax,cs
	mov ds,ax 
	mov si,offset lp  
	mov cx,offset lpend-offset lp 
	cld
	rep movsb
	mov ax,0
	mov es,ax 
	mov word ptr es:[7ch*4],200h
	mov word ptr es:[7ch*4+2],0h
	mov ax,4c00h 
	int 21h
lp:
	push bp 
	mov bp,sp 
	dec cx 			;寄存器CX中存放着循环次数
	jcxz lpret 
	add [bp+2],bx 
lpret:
	pop bp 
	iret 
lpend:
	nop
code ends 
end start

安装结果如下:

请添加图片描述
中断向量表的设置情况如下:

请添加图片描述

调用结果如下:

请添加图片描述


2. 检测点 13.1

(1)在预备知识中,用 7ch 中断例程实现 loop 的功能,则上述 7ch 中断例程所能进行的最大转移位移是多少?

  • 上述中断例程进行的位移存放在寄存器 BX 内:
mov bx,offset s-offset se

寄存器 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:
	mov ax,data
	mov ds,ax		;段寄存器DS指向data段
	mov si,0
	mov ax,0b800h
	mov es,ax		;段寄存器ES指向显示区域
	mov di,160*12
s:
	cmp byte ptr [si],0	
	je ok 						;如果上述比较等于零则跳转到标号ok处
	mov al,[si]
	mov byte ptr es:[di],al		;写入字符串内容
	mov byte ptr es:[di+1],2h	;给字符加上绿色属性
	inc si 				;偏移1个字节从字符串取字符
	add di,2			;偏移2个字节得到下一个写入地址
	mov bx,offset s-offset ok ;转移位移
	int 7ch
ok:
	mov ax,4c00h
	int 21h
code ends
end start 
  • jmp near ptr s 实现段内近转移,段寄存器内容不变、(IP)=(IP)+16 位位移,相当于预备知识中的一次循环操作。
  • 由预备知识的内容,由于在中断处理程序中后续会使用寄存器 BP,首先将其入栈。现考虑栈中的数据存放情况,首先栈顶是 ok 的偏移地址,然后是 s 的段地址,然后是标志寄存器。
  • 栈顶偏移地址存放在 SP 中,从栈顶往下数第二个为 ok 的偏移地址,所以 ok 的偏移地址可表示为 (sp)+2,即标号 s 的偏移地址可表示为 ss:((sp)+2)+(bx)。此时,栈中 ok 的偏移地址变为 s 的偏移地址。后续执行 iret 恢复现场后,CS:IP 自动指向标号 s 的地址,完成段内短转移。

综上,程序安装部分和中断处理程序部分为:

assume cs:code
code segment
start:
	mov ax,0
	mov es,ax
	mov di,200h
	mov ax,cs
	mov ds,ax 
	mov si,offset lp  
	mov cx,offset lpend-offset lp 
	cld
	rep movsb
	mov ax,0
	mov es,ax 
	mov word ptr es:[7ch*4],200h
	mov word ptr es:[7ch*4+2],0h
	mov ax,4c00h 
	int 21h
lp:
	push bp 
	mov bp,sp 
	add [bp+2],bx 	;将IP的内容设置为标号s的偏移地址
	pop bp 
	iret 
lpend:
	nop
code ends 
end start

安装结果如下:

请添加图片描述

中断向量表的设置情况如下:

请添加图片描述

调用结果如下:
请添加图片描述


3. 检测点 13.2

判断下面说法的正误:

(1)我们可以编程改变 FFFF:0 处的指令,使得 CPU 不去执行 BIOS 中的硬件系统检测和初始化程序。

FFFF:0 处的指令为一条跳转指令:

请添加图片描述
使用 a 指令向 FFFF:0000 写入一条 mov 指令:

请添加图片描述
再次查看 FFFF:0 处的指令:

请添加图片描述
由图可知,该内存处的指令没有改变,表明该指令是一条可读指令,不可编程写入。

(2)int 19h 中断例程,可以由 DOS 提供。

BIOS 和 DOS 提供的中断例程的安装过程:

  • 开机后,CPU 一加电,初始化 CS:IP=FFFF:0000,跳转执行 BIOS 中的硬件系统检测和初始化程序
  • 将 BIOS 提供的中断例程的入口地址装入中断向量表
  • 硬件系统检测和初始化完成后,调用 int 19h 进行操作系统引导,操作系统接收计算机控制权
  • DOS 启动后,除完成其他工作外,还将它的中断例程装入内存,而 BIOS 的中断例程常驻内存

所以,int19h 不是由 DOS 提供的,因为在 DOS 装入中断例程前 int19h 已存在于内存中。


4. 总结

  • 本文首先介绍了基于 int 7ch 中断实现循环指令的功能,并将其应用于在屏幕显式字符。
  • 然后介绍基于 int 7ch 中断实现 jmp near ptr s 的功能,类似于一次循环的执行。
  • 最后介绍了,BIOS 和 DOS 提供的中断例程的相关内容。

  • 17
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值