zoukankan      html  css  js  c++  java
  • 汇编语言 | 定制键盘输入的处理过程

    汇编语言 | 定制键盘输入的处理过程

    一、键盘输入的处理过程

    1. 键盘产生扫描码
    2. 扫描码送入60h端口
    3. 引发9号中断
    4. CPU执行int 9中断例程,处理键盘输入

    ​ 1.~3.由硬件系统用完成。4.中的int 9中断例程可以由DOS系统提供,也可以按照开发需求定制处理键盘的输入。

    二、编程任务分析

    • 在屏幕中间依次显示'a'~'z',并可以让人看清

    • 在显示的过程中按下Esc键后改变显示的颜色

    三、工作策略

    • 尽可能忽略硬件处理细节,充分利用BIOS提供的int 9中断例程处理硬件细节。

    • 在改写后的中断例程中满足特定要求,并能调用BIOS的原int 9中断例程

    四、实现

    (1)依次显示'a'~'z':

    	; 显示'a'-'z'
    	mov ax,0b800h
    	mov es,ax
    	mov ah,'a'
    s:	mov es:[160*12+40*2],ah ; 操作显存,找到中间位置
    	call delay
    	inc ah
    	cmp ah,'z'
    	jna s
    	mov ax,0
    	mov es,ax
    

    ​ 但是这样做字母切换太快,在屏幕上无法看清每个字母的显示。需要在每个字母显示后延时一段时间。

    (2)延时程序:

    ​ 用两个16位寄存器来存放32位的循环次数。一共循环10,0000h次。

    	; 定义延迟程序
    	delay:
    	push ax
    	push dx
    	mov dx,10h
    	mov ax,0
    s1:
    	sub ax,1
    	sbb dx,0
    	cmp ax,0
    	jne s1
    	cmp dx,0
    	jne s1
    	pop dx
    	pop ax
    	ret
    

    (3)按下Esc键后改变显示的颜色

    ​ 键盘输入到达60h端口后会引发9号中断,CPU会转去执行int 9中断例程。

    ​ (1) 从60h端口读出键盘的输入

    ​ (2) 调用BIOS的int 9中断例程,处理硬件细节

    • 将中断向量表中的int 9中断例程的入口地址改为自编的中断处理程序的入口地址

    • 在新中断例程中调用原有的int 9中断例程,因此仍需保存原来的int 9中断例程的地址

      解决方案:将原来int 9中断例程的偏移地址和段地址保存在ds:[0]和ds:[2]单元中。

      	; 保存旧中断例程入口
      	mov ax,0
      	mov es,ax
      	push es:[9*4]
      	pop ds:[0]
      	push es:[9*4+2]
      	pop ds:[2]
          ; 设置新的中断向量的位置
      	mov word ptr es:[9*4],offset int9
      	mov es:[9*4+2],cs
    

    ​ 调用原int 9指令的中断例程:

    1. 标志寄存器入栈

    2. IF=0, TF=0

    3. CS、IP入栈

    4. (IP) = ((ds)*16 + 0)

      (CS) = ((ds)*16 + 2)

    	pushf    ; 标志寄存器入栈
    	; IF=0, TF=0
    	pushf
    	pop bx
    	and bh,11111100b
    	push bx
    	popf
    	; CS、IP入栈 (IP) = ((ds)*16 + 0) (CS) = ((ds)*16 + 2)
    	call dword ptr ds:[0]
    

    (3) 判断是否为Esc的扫描码,如果是则改变显示颜色。否则直接返回。

    ; 定义中断例程
    int9:
    	push ax
    	push bx
    	push es
    	in al,60h
    	pushf
    	pushf
    	pop bx
    	and bh,11111100b
    	push bx
    	popf
    	call dword ptr ds:[0]
    
    	cmp al,1       ; ESC扫描码1
    	jne int9ret
    	; 改变颜色
    	mov ax,0b800h
    	mov es,ax
    	inc byte ptr es:[160*12+40*2+1]
    
    int9ret:
    	pop es
    	pop bx
    	pop ax
    	iret
    

    五、完整代码

    ; 编写int 9中断例程改变显示的颜色
    ; (1)从60h端口读出键盘的输入 in al,60h
    ; (2)调用BIOS的int 9中断例程, 处理硬件细节
    ; (3)判断是否为Esc扫描码 如果是则改变显示的颜色后返回
    ; 如果不是则直接返回
    assume cs:code
    
    stack segment
    	db 128 dup (0)
    stack ends
    
    data segment
    	dw 0,0
    data ends
    
    code segment
    start:
    	mov ax,stack
    	mov ss,ax
    	mov sp,128
    	mov ax,data
    	mov ds,ax
    	
    	; 更改中断例程的入口地址
    	mov ax,0
    	mov es,ax
    	push es:[9*4]
    	pop ds:[0]
    	push es:[9*4+2]
    	pop ds:[2]
    	
    	mov word ptr es:[9*4],offset int9
    	mov es:[9*4+2],cs
    	
    	; 显示'a'-'z'
    	mov ax,0b800h
    	mov es,ax
    	mov ah,'a'
    s:	mov es:[160*12+40*2],ah
    	call delay
    	inc ah
    	cmp ah,'z'
    	jna s
    	mov ax,0
    	mov es,ax
    
    	; 恢复原来的地址
    	push ds:[0]
    	pop es:[9*4]
    	push ds:[2]
    	pop es:[9*4+2]
    	
    	mov ax,4c00h
    	int 21h
    	
    	; 定义延迟程序
    	delay:
    	push ax
    	push dx
    	mov dx,10h
    	mov ax,0
    s1:
    	sub ax,1
    	sbb dx,0
    	cmp ax,0
    	jne s1
    	cmp dx,0
    	jne s1
    	pop dx
    	pop ax
    	ret
    
    	; 定义中断例程
    int9:
    	push ax
    	push bx
    	push es
    	in al,60h
    	pushf
    	pushf
    	pop bx
    	and bh,11111100b
    	push bx
    	popf
    	call dword ptr ds:[0]
    
    	cmp al,1       ; ESC扫描码为1
    	jne int9ret
    	; 改变颜色
    	mov ax,0b800h
    	mov es,ax
    	inc byte ptr es:[160*12+40*2+1] ; 高8位存放的是字符的属性
    
    int9ret:
    	pop es
    	pop bx
    	pop ax
    	iret
    code ends
    
    end start
    
  • 相关阅读:
    laravel 图片上传与前端显示问题
    laravel elquent distinct 用法
    JQuery跳出each循环的方法(包含数组遍历)
    Laravel分页以及样式——从未如此简单
    Laravel 的 Blade 模板引擎,当数据存在时输出变量
    laravel 图片上传与前端显示问题
    使用Laravel Eloquent ORM 时如何查询表中指定的字段
    Laravel中路由绑定 Controller 包含子目录写法
    php artisan 命令列表
    如何安装 Composer
  • 原文地址:https://www.cnblogs.com/tedukuri/p/14397572.html
Copyright © 2011-2022 走看看