《汇编语言》- 读书笔记 - 第17章-使用 BIOS 进行键盘输入和磁盘读写

《汇编语言》- 读书笔记 - 第17章-使用 BIOS 进行键盘输入和磁盘读写

  • 17.1 int9 中断例程对键盘输入的处理
    • 键盘缓冲区
  • 17.2 使用 int 16h 中断例程读取键盘缓冲区
    • 编程
    • 检测点 17.1
  • 17.3 字符串的输入
    • 编程:字符串输入程序
      • 需求
      • 分析
        • 处理过程
        • 子程序
        • 完整代码
  • 17.4 应用 int 13h 中断例程对磁盘进行读写
    • 3.5 英寸 1.44兆 软盘
    • INT 13H 直接磁盘服务 Direct Disk Service
      • 功能 02H 读扇区
      • 功能 03H 写扇区
    • 编程:将当前屏幕的内容保存在磁盘上
  • 实验 17 编写包含多个功能子程序的中断例程
  • 课程设计 2

17.1 int9 中断例程对键盘输入的处理

键盘缓冲区

CPU响应中断
保存上下文
跳转至 INT 9H 中断服务例程
A
shift + A
按下 左 shift
清除中断请求
恢复上下文
返回至主程序
松开 左 shift
清除中断请求
恢复上下文
返回至主程序
清除中断请求
恢复上下文
返回至主程序
清除中断请求
恢复上下文
返回至主程序
开始
用户按下键
触发中断 INT 9H
60h 端口 读取扫描码
检测状态字节
扫描码 1EhASCII码 61h
扫描码 1EhASCII码 41h
[ 0040:17]第1位置 1
结束
[ 0040:17]第1位置 0
存储到缓冲区
高位= 扫描码,低位= ASCII码
[ 1E61]
存储到缓冲区
高位= 扫描码,低位= ASCII码
[ 1E41]

输入: A、B、C、D、E、Shift_A、A

  • 写入顺序从左➡️右
-123456789ABCDEF
写入前
输入A1E61
输入B1E613062
输入C1E6130622E62
输入D1E6130622E622064
输入E1E6130622E6220641265
输入Shift_A1E6130622E62206412651E41
输入A1E6130622E62206412651E411E61

17.2 使用 int 16h 中断例程读取键盘缓冲区

从键盘缓冲区中读取一个键盘输入,并且将其从缓冲区中删除:

mov ah,0
int 16h

结果: (ah)=扫描码,(al)=ASCII 码。

-读取字符ahal123456789ABCDEF
读取前1E6130622E62206412651E411E61
执行1次A1E6130622E62206412651E411E61
执行2次B30622E62206412651E411E61
执行3次C2E62206412651E411E61
执行4次D206412651E411E61
执行5次E12651E411E61
执行6次Shift_A1E411E61
执行7次A1E61

从上面我们可以看出,int 16h 中断例程的0号功能,进行如下的工作。

  1. 检测键盘缓冲区中是否有数据;
  2. 没有则继续做第1步;
  3. 读取缓冲区第一个字单元中的键盘输入;
  4. 将读取的扫描码送入 ah,ASCII码送入 al;
  5. 将已读取的键盘输入从缓冲区中删除。

BIOS 的 int 9中断例程int l6h中断例程 配合工作。
按键触发 int 9向键盘缓冲区中写入,
应用程序调用 int 16h从缓冲区中读出。

编程

r 设置字符为红色,按 g 设置字符为绿色,按 b 设置字符为蓝色。

assume cs:code
code segmentstart: mov ah,0int 16hmov ah,1cmp al,'r'je redcmp al,'g'je greencmp al,'b'je bluejmp short sretred: shl ah,1green: shl ah,1blue: mov bx,0b800hmov es,bxmov bx,1mov cx,2000s:	and byte ptr es:[bx],11111000bor es:[bx],ahadd bx,2loop ssret: mov ax,4c00hint 21h	
code ends
end start
 划  线 ——说 明 ——————————闪烁背景红背景绿背景蓝高亮前景红前景绿前景蓝
mov ah,1设置颜色为 1,对应蓝色00000001
red: shl ah,1左移一位后成为绿色00000010
green: shl ah,1再左移一位后成为红色00000100
  1. 最开始给 ah 默认值是 0000 0001b 蓝色
  2. 如果是按 r 跳到标号red 向下执行到 blue 总共左移2次。成为红色
  3. 如果是按 g 跳到标号green 向下执行到 blue 总共左移1次。成为绿色
  4. 如果是按 b 跳到标号blue 无需左移。直接使用蓝色
rgb
rg

检测点 17.1

《汇编语言》- 读书笔记 - 各章检测点归档 - 检测点 17.1

17.3 字符串的输入

编程:字符串输入程序

需求

  1. 在输入的同时需要显示这个字符串;
  2. 一般在输入回车符后,字符串输入结束;
  3. 能够删除已经输入的字符。

参考命令行输入场景。

分析

处理过程
开始
调用 int 16h
读取键盘输入
字符键
退格
回车
压入字符栈
从字符栈
弹出一个字符
向字符栈
压入 0
显示所有字符
返回
子程序
  • charstack 入栈、出栈和显示
    我们将上图中的几块业务,拆为子程序来实现。
子程序字符栈的入栈、出栈和显示。
参数(ah)=功能号,0=入栈,1=出栈,2=显示
0 号功能(入栈): (al)=入栈的字符
1 号功能(出栈): (al)=返回的字符
2 号功能(显示): (dh)=行、(dl)=列
参数ds:si 指向字符栈空间
  • getstr 获取字符串
    接收字符串输入,判断后调用:入栈、出栈和显示
完整代码
assume cs:code,ds:datadata segmentmystr db 255 dup(0)	; 声明字符栈
data endscode segmentstart: mov ax,data			; 设置字符栈所在段地址mov ds,axmov ax,offset mystr	; 设置字符栈偏移地址mov di,axcall getstr			; 调用子程序开始字符串输入ok:	mov ax,4c00hint 21h; =======================================================	
; ------------------- 子程序 -----------------
; 接收字符串输入,判断后调用:入栈、出栈和显示
; -------------------------------------------------------
; 参数:无
; 返回:无
; -------------------------------------------------------
getstr:	push ax			; 备份寄存器
getstrs:mov ah,0int 16hcmp al,20hjb nochar		; ASCII码小于20h,说明不是字符mov ah,0call charstack	; 字符入栈mov ah,2call charstack	; 显示栈中的字符jmp getstrs		; 跳开头,重新开始获取输入字符
nochar:cmp ah,0eh		; 对比扫描码,如果是【退格键】跳 backspaceje backspacecmp ah,1ch		; 对比扫描码,如果是【Enter】跳 enterje enterkeyjmp getstrs		; 跳开头,重新开始获取输入字符
backspace:mov ah,1		; 调用子程序 charstack 的功能1 出栈一个字符call charstackmov ah,2		; 调用子程序 charstack 的功能2 显示字符串call charstackjmp getstrs		; 跳开头,重新开始获取输入字符
enterkey:mov ah,0		; 调用子程序 charstack 的功能0 入栈一个字符 cs:38mov al,0		; 入栈的字符 = 0call charstackmov ah,2		; 调用子程序 charstack 的功能2 显示字符串call charstackpop ax			; 还原寄存器ret
; -------------------- 子程序 -----------------
; =======================================================; =======================================================	
; ------------------- 子程序 -----------------
; 字符栈的入栈、出栈和显示
; -------------------------------------------------------
; 参数:(ah)=功能号,0=入栈,1=出栈,2=显示
; 		0 号功能(入栈): (al)=入栈的字符
; 		1 号功能(出栈): (al)=返回的字符
; 		2 号功能(显示): (dh)=行、(dl)=; 参数:ds:si 指向字符栈空间
; -------------------------------------------------------
charstack:jmp short charstart	; 直接跳过数据块,到代码开关table	dw	charpush,charpop,charshow	; 子程序入口
top		dw	0							; 字符串长度charstart:push bx			; 备份寄存器push dxpush dipush es; 检查 ah 功能号:如果>2退出。否则按索引调用子程序	cmp ah,2	ja sretmov bl,ahmov bh,0add bx,bx				; table 是 dw 类型,所以是bx*2jmp word ptr table[bx]	; 调用子程序charpush:				; 字符入栈mov bx,topmov [si][bx],al		; al中的字符,存入 ds:[si+bx]inc top				; top + 1 对应字符串长度jmp sret			; 跳结束charpop:				; 上一个字符出栈cmp top,0			; 如果字符串空了,直接结束je sretdec top				; top - 1 对应字符串长度mov bx,top			mov al,[si][bx]		; 从 ds:[si+bx] 取字符存入 aljmp sret			; 跳结束charshow:				; 显示字符(算出显示位置)mov bx,0b800h		; 设置显存mov es,bxmov al,160			; 每行160字节,用于计算行偏移mov ah,0mul dh				; 行偏移 = 每行字节数al * 行数dhmov di,ax			; 行偏移存入 diadd dl,dl			; 列偏移 = 列号dl * 2 mov dh,0add di,dx			; 显示位置di = 行偏移di + 列偏移dxmov bx,0			; 字符索引置 0 用作是否打印的判断条件charshows:cmp bx,top			; 循环类似于 for(bx=0; bx < top; bx++)jne noempty					; bx == top 时 noemptymov byte ptr es:[di],' '	; 末尾多打个“空格”; 用于覆盖掉被退格的字符jmp sret					; 跳结束noempty:				; 字符串非空,就打印出来mov al,[si][bx]				; 从 ds:[si+bx] 取字符mov es:[di],al				; 显示到 es:[di]mov byte ptr es:[di+2],' '	; 每个字符后插入一个空格; 开路先锋,刷掉屏幕上原有字符,; 让字符串看上去末尾总有个留inc bx						; bx 指向下一个字符add di,2					; di 指向下一个显示字符的位置jmp charshows				; 跳转 charshows 直到所有字符打印完成sret:pop es			; 还原寄存器pop dipop dxpop bxret
; -------------------- 子程序 -----------------
; =======================================================
code ends
end start

17.4 应用 int 13h 中断例程对磁盘进行读写

3.5 英寸 1.44兆 软盘

磁道扇区字节大小
280185121440KB ≈ 4.44M

INT 13H 直接磁盘服务 Direct Disk Service

功能 02H 读扇区

功能02H读扇区
入口参数AH02H
参数AL=扇区数(要读多少扇区)
DL=驱动器,00H~7FH 软盘(0=A,1=B);80H~0FFH 硬盘(80h=C,81h=B)
CH=柱面(磁道号)
DH=磁头(面)
CL=扇区
ES:BX =缓冲区的地址(指向接收数据的内存区)
返回操作成功:ah=0; al=读取的扇区数
操作失败:ah=错误代码

功能 03H 写扇区

功能03H写扇区
入口参数AH03H
参数AL=扇区数(要写多少扇区)
DL=驱动器,00H~7FH 软盘(0=A,1=B);80H~0FFH 硬盘(80h=C,81h=B)
CH=柱面(磁道号)
DH=磁头(面)
CL=扇区
ES:BX =缓冲区的地址(指向要写入磁盘的数据)
返回操作成功:ah=0; al=写入的扇区数
操作失败:ah=错误代码

编程:将当前屏幕的内容保存在磁盘上

分析: 1屏的内容占 4000个字节,需要8个扇区,用0面0道的1~8扇区存储显存中的内容。
1.44M软盘(3.5英寸高密度软盘)每个扇区的字节数是512字节。

assume cs:code
code segmentstart: mov ax,0b800h	; es:bx 指向显示缓存第1页mov es,axmov bx,0mov al,8		; 写入的扇区数mov dl,0        ; A 盘 mov dh,0        ; 磁头mOV ch,0		; 磁道号mov cl,1		; 扇区号mov ah,3        ; 功能03H 写扇区int 13h         ; 调用“直接磁盘服务”ok:	mov ax,4c00hint 21h
code ends
end start

实验 17 编写包含多个功能子程序的中断例程

《汇编语言》- 读书笔记 - 第17章-实验17 编写包含多个功能子程序的中断例程

课程设计 2

《汇编语言》- 读书笔记 - 第17章-课程设计 2

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/519803.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

干货分享③:免费制作产品管理系统!

他来了&#xff0c;他来了&#xff0c;他带着码上飞CodeFlying走来了&#xff01;今天继续为大家带来一期干货分享&#xff0c;教大家如何免费使用码上飞来的开发产品管理系统 &#xff01; 一、登陆官网 码上飞 CodeFlying | AI 智能软件开发平台&#xff01; 点击立即体验注…

官方教程 | 在 OpenBayes 平台进行组织协作

想和好 homie 共享账户余额、存储、数据集、模型、容器等资源&#xff0c;又不想共享自己的账户密码&#xff1f; 想跟团队成员分工协作、高效 Coding、加速炼丹&#xff0c;又想隔离权限、差异化管理&#xff1f; 经过为期半年的内测和完善&#xff0c;OpenBayes贝式计算的组织…

物体检测-系列教程23:YOLOV5 源码解析13 (SPP层、Flatten模块、Concat模块、Classify模块)

&#x1f60e;&#x1f60e;&#x1f60e;物体检测-系列教程 总目录 有任何问题欢迎在下面留言 本篇文章的代码运行界面均在Pycharm中进行 本篇文章配套的代码资源已经上传 点我下载源码 17、SPP模块 17.1 SPP类 SPP是一种特殊的池化策略&#xff0c;最初在YOLOv3-SPP中被使用…

AD20软件使用指南:拼板操作与Gerber文件生成详解

文章目录 一、前言二、拼板1.创建新的PCB&#xff0c;用于放置拼板文件2.放置拼板阵列3.设置阵列信息4.V割拼板&#xff0c;放置工艺边和定位孔和光点5.完成拼板 三、生成Gerber文件1.输出Gerber文件2.选择单位和格式3.选择输出的图层4.生成Gerber文件5.生成钻孔文件 四、上传嘉…

Pytorch学习 day06(torchvision中的datasets、dataloader)

torchvision的datasets 使用torchvision提供的数据集API&#xff0c;比较方便&#xff0c;如果在pycharm中下载很慢&#xff0c;可以URL链接到迅雷中进行下载&#xff08;有些URL链接在源码里&#xff09;代码如下&#xff1a; import torchvision # 导入 torchvision 库 # …

TC397 Tasking CMake Gitlab CI CD 环境配置

文章目录 Aurix Development Studio 新建工程与配置Tasking 环境配置CMake 集成Win CMake MinGW 安装Tasking Toolchain 工具链CMakeLists.txtPowershell 脚本 Gitlab CI CDGithub Link 本篇先演示了ADS新建激活编译工程, 讲述了浮点模型, 链接脚本文件, 静态库集成等的设置, 接…

vue3的开发小技巧

「总之岁月漫长&#xff0c;然而值得等待。」 目录 父组件调用子组件函数如何访问全局api 父组件调用子组件函数 ref, defineExpose //父组件 代码 <child ref"ch">this.$refs.ch.fn();//子组件 函数抛出 const fn () > { }; defineExpose({ fn });如何…

01背包问题 刷题笔记

思路 dp 用f[i][j]来表示当体积为j时 考虑前i件物品可以获得的 最大值 记住f[i][j]本身是个价“价值” 考虑两种状态 是否将第i件物品放入背包里面 将背包的体积从小到大递增来进行考虑 首先 考虑条件 如果当前增加的体积放不下下一件物品 则该体积 可以获得的最大值可以直接…

和为K的子数组

题目&#xff1a; 使用前缀和的方法可以解决这个问题&#xff0c;因为我们需要找到和为k的连续子数组的个数。通过计算前缀和&#xff0c;我们可以将问题转化为求解两个前缀和之差等于k的情况。 假设数组的前缀和数组为prefixSum&#xff0c;其中prefixSum[i]表示从数组起始位…

基于YOLOv5的驾驶员疲劳驾驶行为​​​​​​​检测系统

&#x1f4a1;&#x1f4a1;&#x1f4a1;本文主要内容:详细介绍了疲劳驾驶行为检测整个过程&#xff0c;从数据集到训练模型到结果可视化分析。 博主简介 AI小怪兽&#xff0c;YOLO骨灰级玩家&#xff0c;1&#xff09;YOLOv5、v7、v8优化创新&#xff0c;轻松涨点和模型轻量…

MySQL事务隔离级别

文章目录 一、前置知识1、为什么要隔离级别&#xff1f;1、隔离级别种类2、查看/设置隔离级别3、手动控制事务4、事务的锁信息查看 二、实战1、READ UNCOMMITTED2、READ COMMITTED3、REPEATABLE READ4、SERIALIZABLE 三、总结 一、前置知识 1、为什么要隔离级别&#xff1f; …

9款世界级垂直领域软件架构师Visio平替作图工具!

1 LucidChart 一个基于HTML5的在线流程图绘制和协作应用平台&#xff0c;用户可以通过它方便快速的实现流程图表的绘制&#xff0c;同时还可以实现与他人进行实时的流程图绘制和修改功能&#xff0c;对需要群组协作功能的团队来说&#xff0c;这点非常方便。 由于LucidChart是…