「汇编语言 第 3 版 王爽」- 参考答案:实验 15 安装新的 int 9 中断例程

  CREATE BY JENKINSBOT
原文链接:「汇编语言 第 3 版 王爽」- 参考答案:实验 15 安装新的 int 9 中断例程
文章分类:「01.Section_of_the_Computer_Hardware:1.CPU_-_Central_Processing_Unit:x86_Assembly_Language:ISBN_-_9787302333142:EXP_15」
文章标识:「af3112ce」

参考答案

实验内容

安装一个新的 int 9 中断例程,功能:在 DOS 下,按下”A”键后,除非不再松开,如果松开,就显示满屏幕的”A”,其他的键照常处理

提示:按下一个键时产生的扫描码称为通码,松开一个键产生的扫描码称为断码。断码=通码+80h

实验分析

使用老套路:
1)旧中断例程地址复制到别处,设置新中断例程地址。
2)新中断例程调用旧中断例程,另外如果是 A 的断码,就写入显存全变 A

汇编实现

assume cs:codeseg

codeseg segment

	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	;; 新的中断程序
	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
print_aaa:
	push ax
	push ds
	push si
	push cx
		
	; 执行原有中断例程,其他的键照常处理
	pushf 
	call dword ptr cs:[0200H]
	
	in al, 60H			; 读取键盘扫描码
	cmp al, 80H + 1EH	; 判断是否为 A 的断码
	jne print_aaa_iret	; 如果不是 A 的断码,则返回
	
	; 向显存写入 A,我们只写入第一页
	mov ax, 0B800H
	mov ds, ax
	mov si, 0
	
	mov cx, 80 * 25	; 只写入第一页,= 80 * 2 * 25 / 2
	loop_s0:
		mov byte ptr ds:[si], 'A'
		add si, 2
		loop loop_s0
	
	print_aaa_iret:
	pop cx
	pop si
	pop ds
	pop ax
	iret
print_aaa_end:

	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	;; 复制中断程序
	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
start:
	mov ax, cs					; 设置起始地址
	mov ds, ax
	mov si, offset print_aaa
	mov ax, 0000H				; 设置目的地址
	mov es, ax
	mov di, 0204H
	mov cx, offset print_aaa_end - offset print_aaa
	cld
	rep movsb
	
	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	;; 设置中断向量表
	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	mov ax, 0
	mov es, ax
	
	; 复制旧地址到 0000:0200 处 ;
	push es:[9 * 4]		; IP
	pop es:[0200H]		; IP
	push es:[9 * 4 + 2]	; CS
	pop es:[0202H]		; CS
	
	; 设置新地址
	cli
	mov word ptr es:[9 * 4], 0204H
	mov word ptr es:[9 * 4 + 2], 0
	sti
	
	mov ax, 4C00H
	int 21H

codeseg ends

end start

附加说明

有个地方我一直还没弄明白:在 debug 中在 debug 外,有什么区别。有这么个现象:
1)执行上述程序,安装中断例程。在程序运行结束后,再次返回终端,显示提示符(C:\>);
2)此时按 A 键,不会显示满屏的 A 字符;
3)当我们执行 debug any.exe 进入调试模式时,此时按 A 键,会显示满屏的 A 字符;

参考文献

CSDN/汇编语言王爽第三版答案
百度文库/汇编语言实验答案 (王爽)