⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 int9.asm

📁 基于asm汇编语言实现的是在pc系统中int9中断功能的部分示例,只在说明机制,进行学习,不能实际应用
💻 ASM
字号:
.model small
.386
.stack
.data
;scan code(base=0)   1	 2	3	 4  5  6  7  8  9  0  -  =  \t q   w   e   r   t   y   u   i   o   p   [  ]   \n   a  s   d   f    g  h   j   k   l    ;  '  `    \   z    x   c  v   b  n   m   ,  .  /  
scan_tab_dn db   ?,?,49,50,51,52,53,54,55,56,57,48,45,61,?,9,113,119,101,114,116,121,117,105,111,112,91,93, 13,?,97,115,100,102,103,104,106,107,108,59,39,96,? ,92, 122,120,99,118,98,110,109,44,46,47
scan_tab_up db   ?,?,33,64,35,36,37,94,38,42,40,41,95,43,?,9,81 ,87, 69, 82, 84, 89, 85, 73, 79, 80,123,125,13,?,65,83, 68, 70, 71, 72, 74, 75, 76, 58,34,126,?,124,90, 88, 67, 86,66,78, 77 ,60,62,63

.code
main 	proc far
start:
			mov 	ax,@data
			mov 	ds,ax
	
;save old interrupt vector
			mov		al,9
			mov		ah,35h
			int 	21h
			push 	es
			push	bx
			push	ds

;set new interrupt vector
			mov 	dx,offset myint9
			mov 	ax,seg myint9
			mov		ds,ax
			mov 	al,9
			mov		ah,25h
			int		21h

;restore ds and set mask code
			pop		ds		
			in		al,21h
			and 	al,11111101b
			out 	21h,al

;open interrupt
			sti
			
;clear key-board buffer
			call		mem_clr
			
waitint9:
;两套测试方案
;			mov		ah,0
;			int		16h
;			mov		dl,al
;			mov		ah,2
;			int 	21h
			mov		ah,7
			int 	21h
			mov		dl,al
			mov		ah,2
			int		21h
			jmp		waitint9


;restore old interrupt vector
			pop 	dx
			pop		ds
			mov		al,9h
			mov		ah,25h
			int		21h
	
;exit
			mov 	ax,4c00h
  		int 	21h
	
main 	endp

;===================================================

myint9	proc	near

			;保存寄存器
			cli
			push 	ax
			push	bx
			push	cx
			push	dx
			push	si
			push 	di
			push	es
			xor 	cx,cx
			
;等待数据输入,超时则退出
waitdata:
			;if outport code ready
			;读键盘状态接口
			in		al,64h
			
			;检测是否数据已放入缓冲区
			test 	al,01b
			
;not ready,wait for a moment
			loopz	waitdata

;not ready and time out,quit interrupt procedure
			jz		_quit1
			jnz		next1
			
_quit1:
			jmp		quitint9
			
next1:
			;由8042芯片的60端口接收数据
			in		al,60h

;if code error,quit int-procedure
			;相等说明错误,推出程序
			cmp 	al,0ffh
			jz		_quit2
			jnz		next2
			
_quit2:
			jmp		quitint9
			
next2:
;make es:[si] point to 40:17h unit
			mov		si,17h
			mov		bx,40h
			mov		es,bx
			
;code valid
			;相等说明是右shift键按下,并对其处理
			cmp		al,36h
			jnz		not_rshiftdn
			or		byte ptr es:[si],00000001b
			
not_rshiftdn:
			;相等说明是右shift键弹起,并对其处理
			cmp		al,0b6h
			jnz		not_rshiftup
			and		byte ptr es:[si],11111110b
			
not_rshiftup:
			;相等说明是左shift键按下,并对其处理
			cmp		al,2ah
			jnz		not_lshiftdn
			or		byte ptr es:[si],00000010b
			
not_lshiftdn:
			;相等说明是左shift键弹起,并对其处理
			cmp		al,0aah
			jnz		not_lshiftup
			and		byte ptr es:[si],11111101b
			
not_lshiftup:
			;相等说明是ctrl按下,并对其处理
			cmp		al,1dh
			jnz		not_ctrldn
			or		byte ptr es:[si],00000100b
			
not_ctrldn:
			;相等说明是ctrl键弹起,并对其处理
			cmp		al,9dh
			jnz		not_ctrlup
			and		byte ptr es:[si],11111011b
			
not_ctrlup:
			;相等说明是alt键按下,并对其处理
			cmp		al,38h
			jnz		not_altdn
			or		byte ptr es:[si],00001000b
			
not_altdn:
			;相等说明是alt键弹起,并对其处理
			cmp		al,0b8h
			jnz		not_altup
			and		byte ptr es:[si],11110111b
			
not_altup:
			;相等说明是scroll键,并对其处理
			cmp		al,46h
			jnz		not_scroll
			xor		byte ptr es:[si],00010000b
			
not_scroll:
			;相等说明是num lock键,并对其处理
			cmp		al,45h
			jnz		not_numlock
			xor		byte ptr es:[si],00100000b
			
not_numlock:
			;相等说明是caps lock键,并对其处理
			cmp		al,3ah
			jnz		not_capslock
			xor		byte ptr es:[si],01000000b
			
not_capslock:
			;相等说明是insert键,并对其处理
			cmp		al,52h
			jnz		not_insert
			xor		byte ptr es:[si],10000000b
			
not_insert:
			;相等说明是esc键
			cmp		al,01h
			jnz		not_esc
			;留做地esc键的处理
			
not_esc:
			;如果比35h小,可能是asc码,否则不是
			cmp		al,35h
			ja		not_asc
			
			;将si指向buffer头,di指向buffer尾
			mov		si,es:[1ah]
			mov		di,es:[1ch]
			
			
			;将扫描码转化为asc码,扫描码放于ah,转化后的asc码放入al
			call	scan_to_asc
									
			;将ax存入缓冲区,根据zf的值可以知道存储是否成功
			call	store_code
			jmp		quitint9
			
not_asc:
			;在这里留做扩展,填加代码对更多的键进行处理
			jmp		quitint9
	
quitint9:	
			;准备结束硬中断的指令
			cli
			mov 	al,20h
			out		20h,al
			
			;恢复原寄存器内容,准备推出中断
			pop 	es
			pop 	di
			pop 	si
			pop		dx
			pop		cx
			pop 	bx
			pop 	ax			
			iret
			
myint9	endp


;---------------------------------------
;清空键盘缓冲区

mem_clr		proc	near

			pusha
			
			;将首尾指针指向初始位置
			mov		bx,40h
			mov		es,bx
			mov		word ptr es:[1ah],001eh
			mov		word ptr es:[1ch],001eh
			
			;预备处理bx值
			mov		bx,1eh
			mov		cx,24h
			dec		bx
						
			;将键盘缓冲区内容全清为0
again1:
			inc		bx
			mov		byte ptr es:[bx],0	
			cmp		bx,3dh
			jl		again1
			
			popa
			
			ret
			
mem_clr		endp

;---------------------------------------
;将扫描码转换成asc码,参数在al中,结果在ax中,ah为扫描码,al为字符码

scan_to_asc	proc	near
			;保存寄存器内容
			push	bx
			push	cx
			push	dx
			push	ds
			
			
			;设置es,ds值
		;;;;;;;;;;;;;;;;;;;;;
		;;;mov		ax,@data;;;
		;;;mov		ds,ax;;;;;;
		;;;;;;;;;;;;;;;;;;;;;
			mov		bx,seg scan_tab_up
			mov		ds,bx
			mov		bx,40h
			mov		es,bx
			
			;比35小,则可以转化成asc码,否则不可以,跳出子程序
			cmp		al,35h
			jg		pre_quit
			jmp		pre_xlat
			
pre_quit:
			;将结果制为全1,以显示不可以转化成asc码
			mov		al,0ffh
			jmp		quit_xlate

pre_xlat:
			;转化部分代码
			;将扫描码放入ah
			mov		ah,al
			
			;将键盘状态字存入cl
			;mov		bx,17h
			mov		cl,es:[17h]
			
			;测试是否caps lock键按下奇数次
			test	cl,01000000b
			jnz		caps_lock
			
			;测试是否右shift键按下
			test	cl,00000001b
			jnz		shift_down
			
			;测试是否左shift键按下
			test	cl,00000010b
			jnz		shift_down
			
			;程序运行到这里,说明转化的目标asc码是下档键,结果放入al
			mov		bx,offset scan_tab_dn
			xlat
			jmp		quit_xlate
			
shift_down:
			;程序运行到这里说明shift键已按下,转化目标为上档键,结果放入al
			mov		bx,offset scan_tab_up
			xlat
			jmp		quit_xlate
			
caps_lock:
			;程序运行到这里说明caps lock键已按下奇数次
			test	cl,00000001b
			jnz		caps_shift
			
			;看是否同时又有shift键按下
			test	cl,00000010b
			jnz		caps_shift
			
			;目标为上档键
			mov		bx,offset scan_tab_up
			xlat
			jmp		quit_xlate
			
caps_shift:
			;目标为下档键
			mov		bx,offset scan_tab_dn
			xlat

quit_xlate:
			;预备跳出,恢复寄存器
			pop		ds
			pop		dx
			pop		cx
			pop		bx
			
			ret
			
scan_to_asc	endp

;---------------------------------------
;the code to be stored is in ax,zf=1 failed,zf=0,succeed

store_code proc	near

			;关中断,使过程不能被可屏蔽中断中断
			cli
			
			;保存寄存器内容
			push	bx
			push	cx
			push	dx
			
			;首指针预加2
			add		di,2
			
			;看是否指向地址已经超出缓冲区
			cmp		di,3dh
			
			;超出后,将其指向头部
			ja		to_head
			
			;否则,直接将内容存入缓冲区
			mov		es:[di-2],ax
			
			;置zf为 0
			mov		cx,0
			cmp		cx,1
			jmp		quit_store
			
to_head:
			;新加入的内容放入头部
			sub		di,20h
			mov		es:[3ch],ax
			
			;set zf=0
			mov		cx,0
			cmp		cx,1
			jmp		quit_store

quit_store:
			;准备跳出
			cli
						
			;将新的尾指针写回原空间
			mov		es:[1ch],di
			
			;call	memshow
			pop		dx
			pop		cx
			pop		bx
			
			ret
			
store_code endp
			

;---------------------------------------
;输出寄存器dl的内容,以16进制显示

displaydl	proc near
;save registors
			push	ax
			push 	bx
			push 	cx
			push  dx
	
;save dl into bl
			mov		bl,dl
			
;output the higer 4-bit
			and 	dl,11110000b
			mov 	cl,4
			rol 	dl,cl
			cmp 	dl,1001b		
			jg 		char1				;between a and f
			add 	dl,48				;between 0 and 9
			jmp 	show1
			
char1:
;output code between a and f
			add 	dl,55
			
show1:	
;output code between 0 and 9
			mov 	ah,2
			int 	21h
	
;output the lower 4-bit
			mov 	dl,bl
			and 	dl,00001111b
			cmp 	dl,1001b
			jg 		char2				;between a and f
			add 	dl,48				;between 0 and 9
			jmp 	show2
			
char2:
;output code between a and f
			add 	dl,55
			
show2:
;output code between 0 and 9
			mov 	ah,2
			int 	21h

;output a blank space
			mov 	dl,' '
			mov 	ah,2
			int 	21h

;restore registors
			pop 	dx
			pop 	cx
			pop 	bx
			pop 	ax
	
			ret
displaydl	endp


;---------------------------------------
;display the content of keyboad buffer(40:1e--40:3d),including head(40:1a) and tai(40:1c)

memshow proc near

;save registors
			pusha
	
;set es be the base address of the buffer(40)
			mov	  bx,40h
			mov	  es,bx
			mov 	bx,1ah
	
;prepration for the loop below
			mov		cx,24h
			sub	  bx,1	
			
again:
;display the buffer
			inc	  bx
			mov   dl,es:[bx]
			call  displaydl
			cmp 	bx,3dh
			jl	  again
	
;restore the registors
			popa

			ret
			
memshow endp
	
			end start

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -