鱼C论坛

 找回密码
 立即注册
查看: 1962|回复: 0

[技术交流] 实验15的详细讲解

[复制链接]
发表于 2012-6-19 13:16:09 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
  1. ;本程序中用入栈、出栈的方式完成了 数据 在不同的寄存器之间的交换
  2. ;可以减少代码量,是个很不错的方法
  3. assume cs:code,ss:stack

  4. stack segment
  5.         db 128 dup (0)        ;定义128个字节空间,用于中转数据
  6. stack ends

  7. code segment

  8. start:
  9.                 mov ax,stack
  10.                 mov ss,ax
  11.                 mov sp,128

  12. ;安装中断例程到0:204
  13.                 push cs
  14.                 pop ds                                                                ;设置ds为代码段

  15.                 mov ax,0
  16.                 mov es,ax                                                        ;设置附加段

  17.                 mov si,offset int9                                        ;设置ds:si指向源地址
  18.                 mov di,204h                                                        ;设置es:di指向目的地址0:204h
  19.                 mov cx,offset int9end - offset int9        ;设置cx为传输长度
  20.                 cld                                                                        ;设置传输方向为正
  21.                 rep movsb                                                        ;安装自定义的int9中断例程

  22. ;保存旧的int9中断向量到0:200h-203h
  23.                 push es:[9*4]
  24.                 pop es:[200h]
  25.                 push es:[9*4+2]
  26.                 pop es:[202h]

  27. ;设置新的int9中断向量为0:204h
  28.                 cli                                                                        ;置IF=0,CPU禁止响应外部中断
  29.                 mov word ptr es:[9*4],204h                        ;(0:9*4)=204h
  30.                 mov word ptr es:[9*4+2],0                        ;(0:9*4+2)=0
  31.                 sti                                                                        ;置IF=1,使CPU允许向应外部中断
  32.                
  33. ;进行88次读取BIOS键盘缓冲区的操作,也就是说程序响应你按键多少次
  34.                 mov cx,88
  35.         lp:        mov ah,0
  36.                 int 16h
  37.         loop lp
  38. ;这段代码是方便测试的

  39.                 mov ax,4c00h
  40.                 int 21h

  41. int9:        ;自定义的int9中断例程
  42.                 push ax
  43.                 push bx
  44.                 push cx
  45.                 push es

  46.                 in al,60h                                        ;从60h端口读入数据

  47.                 pushf                                                ;保存标志寄存器,对应下面的iret返回

  48.                 call dword ptr cs:[200h]        ;当此中断例程执行时(CS)=0

  49.                 cmp al,9eh                                        ;判断是否为A的断码9eh
  50.                 jne int9ret

  51.                 mov ax,0b800h                                ;设置显示缓冲区
  52.                 mov es,ax
  53.                 mov bx,0                                        ;偶数位为字符码位
  54.                 mov cx,2000
  55.         s:        mov byte ptr es:[bx],'A'        ;第0屏字符码位全用'A'填充
  56.                 add bx,2
  57.         loop s

  58. int9ret:
  59.                 pop es
  60.                 pop cx
  61.                 pop bx
  62.                 pop ax
  63.                 iret                                                ;popf; ret

  64. int9end:nop

  65. code ends

  66. end start
复制代码
另外附上15.5,
  1. assume cs:code,ss:stack

  2. stack segment
  3.         db 128 dup (0)        ;定义128个字节空间,用于中转数据
  4. stack ends

  5. code segment

  6. start:
  7.                 mov ax,stack
  8.                 mov ss,ax
  9.                 mov sp,128

  10. ;安装中断例程到0:204
  11.                 push cs
  12.                 pop ds                                                                ;设置ds为代码段

  13.                 mov ax,0
  14.                 mov es,ax                                                        ;设置附加段

  15.                 mov si,offset int9                                        ;设置ds:si指向源地址
  16.                 mov di,204h                                                        ;设置es:di指向目的地址0:204h
  17.                 mov cx,offset int9end - offset int9        ;设置cx为传输长度
  18.                 cld                                                                        ;设置传输方向为正
  19.                 rep movsb                                                        ;安装自定义的int9中断例程

  20. ;保存旧的int9中断向量到0:200h-203h
  21.                 push es:[9*4]
  22.                 pop es:[200h]
  23.                 push es:[9*4+2]
  24.                 pop es:[202h]

  25. ;设置新的int9中断向量为0:204h
  26.                 cli                                                                        ;置IF=0,CPU禁止响应外部中断
  27.                 mov word ptr es:[9*4],204h                        ;(0:9*4)=204h
  28.                 mov word ptr es:[9*4+2],0                        ;(0:9*4+2)=0
  29.                 sti                                                                        ;置IF=1,使CPU允许向应外部中断
  30.                
  31. ;进行88次读取BIOS键盘缓冲区的操作,也就是说程序响应你按键多少次
  32.                 mov cx,88
  33.         lp:        mov ah,0
  34.                 int 16h
  35.         loop lp
  36. ;这段代码是方便测试的

  37.                 mov ax,4c00h
  38.                 int 21h

  39. int9:        ;自定义的int9中断例程
  40.                 push ax
  41.                 push bx
  42.                 push cx
  43.                 push es

  44.                 in al,60h                                        ;从60h端口读入数据

  45.                 pushf                                                ;保存标志寄存器,对应下面的iret返回
  46.                
  47.                 call dword ptr cs:[200h]        ;当此中断例程执行时(CS)=0

  48.                 cmp al,3bh                                        ;判断是否为F1的通码
  49.                 jne int9ret

  50.                 mov ax,0b800h                                ;设置显示缓冲区
  51.                 mov es,ax
  52.                 mov bx,1                                        ;奇数位为属性值
  53.                 mov cx,2000
  54.         s:        add byte ptr es:[bx],10h        ;每个背景之间相差10h
  55.                 add bx,2
  56.         loop s

  57. int9ret:
  58.                 pop es
  59.                 pop cx
  60.                 pop bx
  61.                 pop ax
  62.                 iret                                                ;popf; ret

  63. int9end:nop

  64. code ends

  65. end start
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-7-16 22:56

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表