![]() |
中国DOS联盟-- 联合DOS 推动DOS 发展DOS --联盟域名:www.cn-dos.net 论坛域名:www.cn-dos.net/forum |
| 游客 | 登录 | 注册 | 会员 | 搜索 | 中国DOS联盟 |
|
中国DOS联盟论坛 现在时间是 2026-08-07 16:19 |
共 48,041 主题排行 / 350,128 发帖 / 今日 3 篇 / 48,252 会员排行 |
| 网络日志(Blog) » 【Redtek】 个人网志(学习笔记) |
| 可打印版本 29,502 / 130 |
| 第91楼 redtek | 发表于 2007-01-08 00:49 |
| 金牌会员 发帖 1,147 积分 2,902 | |
|
【80x86汇编语言学习笔记】 Windows计算器使用小窍门:
在汇编语言学习过程中,需要经常用到计算器(Windows CALC.exe)来计算二进制或是进行数字的对比,将数字分组功能打开,就会看到数字间隔,方便一眼略知位数。 [ Last edited by redtek on 2007-1-7 at 11:50 AM ] 附件 1.GIF (18.51 KiB) |
|
| 第92楼 redtek | 发表于 2007-01-09 03:49 |
| 金牌会员 发帖 1,147 积分 2,902 | |
|
【80x86汇编语言学习笔记】 内中断
中断信息可以来自CPU的内部和外部。 对于8086CPU,当CPU内部有下面情况发生时,将产生相应的中断信息: 1) 除法错误 (中断类型码:0) 2) 单步执行 ( 1) 3) 执行 int0 指令 ( 4) 4) 执行 int 指令 ( int n-提供给CPU的中断类型码) 8086CPU 用称为中断类型码的数据来标识中断信息的来源。 中断类型码为一个字节型数据,可以表示256种中断信息的来源。 中断处理程序 根据CPU的设计,中断类型码的作用就是用来定位中断处理程序。 …… 中断向量表 CPU用8位的中断类型骊通过中断向量表找到相应的中断处理程序的入口地址。 中断向量表就是中断向量的列表。 中断向量,就是中断处理程序的入口地址。 中断向量表,就是中断处理程序入口地址的列表。 中断向量表在内存中保存,其中存放着256个中断源所对应的中断处理程序的入口。 CPU只要知道中断类型码,就可将中断类型码作为中断向量表的表项号,定位相应表项,从而得到中断处理程序的入口地址。 内存 0000:0000 到 0000:03E8 的1000个单元中存放着中断向量表。 对于8086CPU,这个入口地址包括段地址和偏移地址,所以一个表项占两个字。高地址字存放段地址,低地址字存放偏移地址。 提问: 1) 4号中断源对应的中断处理程序的入口地址为:(0000:0010)
2) 存储N号中断源对应的中断处理程序入口的偏移地址的内存单元的地址为:(N*4) 3) 存储N号中断源对应的中断处理程序入口的段地址的内存单元的地址为:(N*4+2) 中断过程 8086CPU在收到中断信息后,所引发的中断过程: 1) 取得中断类型码 2) 标志寄存器的值入栈 3) 设置标志寄存器的第8位TF和第9位IF的值为0 4) CS的内容入栈 5) IP的内容入栈 6) 从内存地址为 中断类型码*4 和 中断类型码*4+2 的两个字单元中读取中断处理程序的入口地址设置IP和CS。 描述中断过程: 1) 取得中断类型码N 2) pushf 3) TF=0 , IF=0 4) push CS 5) push IP 6) (IP)=(N*4), (CS)=(N*4+2) 中断处理程序 CPU随时都可能检测到中断信息,所以中断处理程序必须一直存储在内存某段空间之中。 中断处理程序的入口地址(中断向量)必须存储在对应的中断向量表项中。 中断处理程序的编写步骤: 1) 保存用到的寄存器 2) 处理中断 3) 恢复用到的寄存器 4) 用 iret 指令返回 iret 指令的功能用汇编语法描述为: pop IP pop CS popf iret 通常和硬件自动完成的中断过程配合使用。 iret指令执行后,CPU回到执行中断处理程序前的执行点继续执行程序。 除法错误中断的处理 CPU执行div等除法指令时,如发生了除法溢出错误,将产生中断类型码为0的中断信息。CPU检测到这个信息,引发中断过程。 编程处理0号中断 编程:当发生了除法溢出错误产生0号中断信息,引发中断过程,CPU执行我们编写的0号中断处理程序。 在屏幕中间显示提示信息: “overflow!” 后,返回到操作系统中。 编写中断处理程序,当中断0发生时: 1) 相关处理 2) 向显示缓冲区送字符串 "overflow!" 3) 返回DOS 8086支持256个中断,实际系统中要处理的中断事件没有达到256个,在中断向量表中有些单元是空的。 从 0000:0200 至 0000:0300 的256个字节的空间所对应的中断向量表项都是空的,操作系统和其他应用程序都不占用。 可以将自己写的中断处理程序扔到内存 0000:0200 处。那么 0000:0200 就是中断入口地址,把它登记在中断向量表的对应表项中。 步骤: 1) 编写可以显示 “overflow!” 的中断处理程序 2) 将程序送入内存 0000:0200 处 3) 将程序的入口地址 0000:0200 存储在中断向量表0号表项中 CMD 不支持直接写屏操作,DOS下支持~:) 当发生除法溢出时,那个字符串就跳了出来,然后返回到dos。
单步中断 CPU在执行完一条指令后,如果检测到标志寄存器的TF位为1,则产生单步中断,引发中断过程。 单步中断的中断类型码为1,引发的中断过程如下: 1) 取得中断类型码1 2) 标志寄存器入栈,TF、IF设置为0 3) CS、IP入栈 4) (ip)=(1*4) , (cs)=(1*4+2) 如果TF=1,则执行一条指令后,CPU就会转去执行1号中断处理程序。 Debug 工具也是这样单步跟踪的原理。 CPU提供单中断功能的原因:为单步跟踪程序的执行过程提供了实现机制。 响应中断的特殊情况 编写0号中断的处理程序 在除法溢出发生时,在屏幕中间显示字符串 "divide rror!",然后返回到DOS。 修改中断向量前、后对比:
[ Last edited by redtek on 2007-1-9 at 12:26 AM ] 附件 1.GIF (7.25 KiB) |
|
| 第93楼 redtek | 发表于 2007-01-09 23:32 |
| 金牌会员 发帖 1,147 积分 2,902 | |
|
【80x86汇编语言学习笔记】 Int 指令
格式: int n 相当于引发一个n号中断的中断过程。 1) 取中断类型码n 2) 标志寄存器入栈,IF=0,TF=0 3) CS、IP入栈 4) (IP)=(n*4), (CS)=(n*4+2) 先运行自编的0号中断程序(安装)并修改中断向量表。(位于92楼 P240.EXE) 然后调用 int 0 引发0号中断: CPU执行 int 0 指令时,将引发中断过程,执行0号中断处理程序。 而0号中断处理程序的功能就是显示一行字符串(如上:92楼0号中断处理程序) int 指令的最终功能和call指令相似,都是调用一段程序。 编写供应用程序调用的中断例程 编写、安装中断7ch的中断例程,功能:求一word型数据的平方。 参数:(AX)=要计算的数据 返回:DX、AX中存放结果的高16位和低16位。 求:2*3456^2 1) 编写实现平方功能程序 2) 安装程序 3) 设置中断向量表,指定入口地址 安装程序 执行过程验证
CPU执行 int 7ch 指令进入中断例程之前,标志寄存器、当前的CS和IP被压入栈中,在执行完中断例程后,用 iert 指令恢复 int 7ch 执行前的标志寄存器和CS、IP的值。 int 指令和 iret 指令的配合使用与 call 指令和 ret 指令的配合使用具有相似的思路。 编写、安装中断7ch的中断例程。 功能:将一个全是字母,以0结尾的字符串转化为大写。 参数:ds:si指向字符串的首地址 7ch 中断例程安装程序 跟踪结果
[ Last edited by redtek on 2007-1-9 at 12:05 PM ] |
|
| 第94楼 redtek | 发表于 2007-01-10 07:38 |
| 金牌会员 发帖 1,147 积分 2,902 | |
|
【80x86汇编语言学习笔记】 对 int、iret和栈的深入理解
) 用 7ch 中断例程完成 jmp near ptr s 指令的功能,用bx向中断例程传送转移位移。 在屏幕的第 12 行显示 data 段中,以 0 结尾的字符串。 调用者: 中断例程: ) 编程:用7ch中断例程完成loop指令的功能。 在屏幕中间显示80个‘!’。 进入中断处理程序之前的压栈次序: 标志寄存器入栈,(TF=0、IF=0); CS入栈 IP入栈 (IP)=(N*4), (CS)=(N*4+2) ------------------------------------------------------- 16位 最后,栈指针(SP)指向最后入栈的16位内容所在的地址。 7ch中断例程……当CPU进行一系列动作时,其压入IP的内容并不是在调用程序中的 int 7ch 所在的IP。 根据CPU执行指令的原理,当CPU读入IP所指向地址的指令时,CPU会另IP指向一下条指令。 所以,当调用 int 7ch 中断之前,CPU 所压入的 IP 是指向一下条指令的,是为了准备执行完当前 int 指令后返回继续执 行之备。 所以,被压入栈的 IP 就是调用代码中“se: nop”这行 se 标号所在的地址~:) 而且,当要 pop 弹出时,则应逆序要弹出的也是 IP ,所以进入 int 7ch 中断处理程序后,其 SP 一直指向 IP 。 当执行 7ch 中断例程时,调用者已将从 se 到 s 标号的位移(使用 offset 指令计算的)存到了 bx 中。 然后将 CS:IP 指向 s 标号(就是将 CS 指向 s 所在的段地址,让 IP 指向 S 所在的偏移地址就行了)。 当 int 7ch 中断例程内,将栈中所压的 IP 与 CS 值改写以后,当执行 iret 指令时,CPU会自动恢复中断前的寄存器 的值,但这值已被我们修改,所以恢复的就是我们修改过的 CS:IP(它指向了 s 标号处)。 下面是调试出错的代码,当 dec cx (递减)时,cx=0 时再递减就发生了为负值,结果进入了死循环。
原来在 int 7ch 中多写了一个 dec cx ,jczx 的判断为0语句被夹在中间,这样它永远也不能正确。 调用者: 7ch 中断例程安装 ) 上面的内容中,用 7ch 中断例程实现 loop 的功能,上面的 7ch 中断例程所能进行的最大转移位移是多少? 因为 loop 位移是 short 型段内短转移指令。 它的位移量是有符号数,最大位移范围是: -128 ~~ + 127 运行界面 [ Last edited by redtek on 2007-1-9 at 09:46 PM ] 附件 1.GIF (11.38 KiB) |
|
| 第95楼 redtek | 发表于 2007-01-10 10:50 |
| 金牌会员 发帖 1,147 积分 2,902 | |
|
【80x86汇编语言学习笔记】 BIOS和DOS所提供的中断例程
在系统板的ROM中存放着一套程序,称为BIOS(基本输入输出系统),BIOS中主要包括: 1) 硬件系统的检测和初始化程序 2) 外部中断和内部中断的中断例程 3) 用于对硬件设备进行 I/O 操作的中断例程 4) 其他和硬件系统相关的中断例程。 操作系统DOS也提供了中断例程。 从操作系统角度来看DOS的中断例程就是操作系统向程序员提供的编程资源。 BIOS和DOS所有提供的中断例程中包含了许多子程序。程序员在编程的时候可以用int指令直接调用中断例程来完成工作。 BIOS和DOS中断例程的安装过程: 1) 开机后,CPU加电,初始化(CS)=0FFFFH,(IP)=0。 自动从FFFF:0单元开始执行程序。 FFFF:0处有一条跳转指令,CPU执行该指令后,转去执行BIOS中的硬件系统检测和初始化程序。 2) 初始化程序将建立BIOS所支持的中断向量,即将BIOS提供的中断例程的入口地址登记在中断向量表中。 对于BIOS所提供的中断例程,只需将入口地址登记在中断向量表中即可,因它是固化到ROM中的程序,一直在内存中。 3) 硬件系统检测和初始化完成后,调用 int 19h 进行操作系统的引导。从此将计算机交由操作系统控制。 4) DOS启动后,除完成其他工作外,还将它所提供的中断例程装入内存,并建立相应的中断向量。 BIOS中断例程应用 一个供程序调用的中断例程中往往包括多个子程序,中断例程内部用传递进来的参数来决定执行哪一个子程序。 BIOS和DOS提供的中断程序,都用AH来传递内部子程序的编号。 int 10h 中断例程设置光标位置 置光标位置用在批处理里,可以将光标定位在屏幕的任何地方。 再使用 SET /P=要显示的文字 <NUL 就可以完成类似“填表格”等特殊显示应用。 关于BIOS或是DOS功能调用专门有手册可以查阅,除特殊情况基本都不用记背。 bh 中的页号的含义,显示缓冲区分为8页。(80*25彩色字符模式)每页 160每行 * 25行 = 4000 字节。 int 10h 中断例程在当前光标位置处写属性和字符 在屏幕的5行12列显示红底高亮闪烁(cmd全屏下闪烁无效)绿色的'a'。 颜色属性
DOS中断例程应用 int 21h中断例程是DOS提供的中断例程,其中包含了DOS提供给程序员在编程时调用的子程序。 int 21h 中断例程 4ch 号功能,结束程序(带返回码结束)。 int 21h中断例程在光标位置显示字符串功能 在屏幕的5行12列显示字符串:“Welcome to masm”。 5行(是指从0~5),12例(是指从0~12) $ 本身不显示,起边界作用。 编写应用中断例程 编写并安装 int 7ch 中断例程,功能为显示一个用0结束的字符串,中断例程安装在0:200处。 参数:(DH)=行号,(DL)=列号,(CL)=颜色,DS:SI指向字符串首地址。 inc 7ch 安装程序 调用者 Debug 跟踪观察 int、iret指令执行前后CS、IP和栈中的状态。 编写并安装 int 7ch 中断例程,功能为完成 loop 指令的功能。 参数:(CX)=循环次数, (BX)=位移 在屏幕中间显示80个‘!’。 调用者: int 7ch 安装 需要注意的地方 当使用 BP 寄存器时寻址时,所操作的是 SS: 当使用非 BP 寄存器寻址时,所操作的默认为 DS: 或指定。 ADD ,BX
分别在屏幕的第2、4、6、8行显示四句英文诗,补全程序
[ Last edited by redtek on 2007-1-10 at 04:24 PM ] |
|
| 第96楼 pengfei | 发表于 2007-01-10 11:42 |
| 银牌会员 发帖 485 积分 1,218 来自 湖南.娄底 | |
Originally posted by redtek at 2006-12-10 00:48: 看了兄写的这段学习总结, 感慨良多, 每一点都命中要害. 以前我读书吊儿郎当, 很容易满足, 自学的一年半年里慢慢地找到了学习的方法, 更重要的是磨练了自己的意志, 如果能够做到为了掌握一个知识点连续作战十几个小时, 还有什么困难可以难倒你. Redtek兄说的对, 学习重在理解, 做事做人都在于领悟, 也许苦学几载不如一朝顿悟. 过去一失败就垂头丧气, 现在觉得失败或许也是成功的预兆, 要善于失败之后找出自己的不足, 设法弥补它. 思想是重要的, 做任何事情, 自己的决心和态度往往是成败的关键. 开弓没有回头箭, 坚持下去你就是最强的, 最后送兄一句: 得意失意, 切莫在意. 顺境逆境, 切莫止境! |
|
| 第97楼 GOTOmsdos | 发表于 2007-01-10 12:01 |
| 铂金会员 发帖 1,827 积分 5,154 | |
|
支持!
我学C的情景跟redtek兄学汇编差不多,千军万马中冲出一条血路! |
|
| 第98楼 redtek | 发表于 2007-01-10 22:17 |
| 金牌会员 发帖 1,147 积分 2,902 | |
|
“得意失意, 切莫在意. 顺境逆境, 切莫止境! ”,欣赏~~~
听pengfei兄讲学习感受和GOTOmsdos兄的鼓励真是受益非浅~:))) |
|
| 第99楼 redtek | 发表于 2007-01-11 05:30 |
| 金牌会员 发帖 1,147 积分 2,902 | |
|
【80x86汇编语言学习笔记】 端口
各种存府器都和CPU的地址线、数据线、控制线相连。 CPU在操控它们的时候,把它们都当作内存来对待,把它们总的看做一个由若干存储单元组成的逻辑存储器,称其为内存地址空间。 PC机系统中,和CPU通过总线相连的芯片除各种存储器外,还有以下3种芯片: 1) 各种接口卡(网卡、显卡、……)上的接口芯片,它们控制接口卡进行工作 2) 主板上的接口芯片,CPU通过它们对部分外设进行访问 3) 其他芯片,用来存储相关的信息,或进行相关的输入输出处理 从CPU角度,将这些寄存器都当作端口,对它们进行统一编址,从而建立了一个统一端口地址空间。每个端口在地址空间中都有一个地址。 CPU可以直接读写3个地方的数据: 1) CPU内部的寄存器 2) 内存单元 3) 端口 端口的读写 访问端口时CPU通过端口地址来定位端口,端口所在芯片和CPU通过总线相连。端口地址和内存地址一样,通过地址总线来传送。 CPU最多可以定位64K个不同的端口。端口地址的范围为: 0~65535。 in 和 out。 访问端口: in al,60h ; 从60h号端口读入一个字节 执行时与总线相关的操作: 1) CPU通过地址线将地址信息60H发出 2) CPU通过控制线发出端口读命令,选中端口所在的芯片,并通知它,将要从中读取数据 3) 端口所在的芯片将60H端口中的数据通过数据线送入CPU 在in和out指令中,只能使用ax或al来存放从端口中读入的数据或要发送到端口中的数据。 访问8位端口时用al,访问16位端口时用ax。 对0~255以内的端口进行读写时: in al,20h ; 从20H端口读入一个字节 out 20h,al ; 往20H端口写入一个字节 对256~65535的端口进行读写时,端口号放在dx中: mov dx,3f8h ; 将端口号3F8H送入dx in al,dx ; 从3F8H读入一个字节 out dx,al ; 向3F8H端口写入一个字节 CMOS RAM芯片 0~0DH单元保存时间信息,其余大部分用于保存系统配置信息,供系统启动时BIOS程序读取。 芯片内部有两个端口,端口地址为70H和71H。CPU通过这两个端口写CMOS RAM。 70H为地址端口,存放要访问的CMOS RAM单元地址 71H为数据端口,存放从选定的CMOS RAM单元中读取的数据。 CPU对CMOS RAM的读写分两步进行。 例:读CMOS RAM的2号单元: 1) 将2送入端口70H 2) 从71H读出2号单元的内容 读取CMOS RAM的2号单元内容 向CMOS RAM的2号单元写入0 CMOS RAM中存储的时间信息 CMOS RAM 各字节的含义(部分): =============================================================== 偏移值(Offset) 数据字段的意义描述(Description) --------------------------------------------------------------- 00h 目前系统时间的“秒数”字段 01h 预约警铃时间的“秒数”字段 02h 目前系统时间的“分钟”字段 03h 预约警铃时间的“分钟”字段 04h 目前系统时间的“小时”字段 05h 预约警铃时间的“小时”字段 06h 星期几(星期一=01,星期二=02,依次类推) 07h 目前系统日期字段(0~31) 08h 系统公元纪年的后两位(00~99;00=2000,01=2001,以此类推) (关于上面BIOS更详细的内容,传说中有一本书,研读完了可以自己开发BIOS,哈哈……) (关于这本书的介绍: 《BIOS研发技术剖析》 )
索引CMOS内容对照(摘自互联网,原作者不详)
在 CMOS RAM中,存放着当前的时间:年、月、日、时、分、秒。这6个信息的长度都为1个字节,存放见上面列表。 这些数据以 BCD 码的方式存放。 BCD码是以4位二进制数表示十进制数码的编方法。 例:数值 26,用BCD码表示为:0010 0110 一个字节可以表示两个BCD码。 CMOS RAM存储时间信息的单元中,存储了用两个BCD码表示的两位十进制数,高4位BCD码表示十位,低4位BCD码表示个位。 例:00010100B表示14。 编程:在屏幕中间显示当前的月份。 编程:以 “年/月/日 时:分:秒” 的格式,显示当前日期、时间。 [ Last edited by redtek on 2007-1-11 at 08:36 PM ] 附件 1.GIF (6.59 KiB) |
|
| 第100楼 lxmxn | 发表于 2007-01-11 09:29 |
| 版主 发帖 4,938 积分 11,386 | |
|
好久没有来兄这里看了,惭愧…… 好想和兄一起学习汇编,但是由于学业比较繁重,很多课程都来不及搞,所以只有先把汇编放一放了,等有时间再来和兄一起学习汇编,呵呵,恐怕到那时候兄已经是汇编牛人了,^_^ |
|
| 第101楼 redtek | 发表于 2007-01-11 23:35 |
| 金牌会员 发帖 1,147 积分 2,902 | |
|
等兄有时间了我们一起学习更多更好玩的东东~:)
经常看到批处理区兄的精彩代码,水平越来越高,真是为之高兴~:) 希望经常看到兄的创造性思想和好玩的代码~:))) |
|
| 第102楼 redtek | 发表于 2007-01-11 23:50 |
| 金牌会员 发帖 1,147 积分 2,902 | |
|
【80x86汇编语言学习笔记】 逻辑移位指令
shl和Shr逻辑移位指令。 shl 左移 shr 右移 SHL逻辑左移指令,功能: 1) 将一个寄存器或内存单元中的数据向左移位 2) 将最后移出的一位写入CF中 3) 最低位用0补充 指令: 结果:
返回值144(十进制)它的二进制是:10010000B ,左移了一位~:) 最后移出的一位写入CF中 红色标示CF 绿色标示结果
如果移动位数大于1时,必须将移动位数放在CL中。 左移了3位,值:10001000B 右移,与左移shl操作相反。 1) 将一个寄存器或内存单元中的数据向右移位 2) 将最后移出的一位定入CF中 3) 最高位用0补充 将X逻辑左移一位,相当于执行 X=X*2 将X逻辑右移一位,相当于执行 X=X/2 编程:用加法和移位指令计算(AX)=(AX)*10 加法运算(AX)=(AX)*10 运算 3*10 结果
移位指令计算(AX)=(AX)*10 计算 3*10 X左移1位就相当于X*2 X左移2位………… X*4 X左移3位………… X*8 (AX)*10=(AX)*2+(AX)*8 (AX)*10=(AX)左移1位+(AX)左移3位 [ Last edited by redtek on 2007-1-11 at 12:08 PM ] |
|
| 第103楼 ccwan | 发表于 2007-01-12 06:54 |
| 金牌会员 发帖 1,160 积分 2,725 来自 河北廊坊 | |
|
这样的网志堪称经典了,向兄学习。
|
|
| 第104楼 redtek | 发表于 2007-01-12 09:39 |
| 金牌会员 发帖 1,147 积分 2,902 | |
|
有ccwan兄的不断鼓励,我准备把这网志写溢出了,哈哈……
[ Last edited by redtek on 2007-1-11 at 08:44 PM ] |
|
| 第105楼 redtek | 发表于 2007-01-12 09:44 |
| 金牌会员 发帖 1,147 积分 2,902 | |
|
【80x86汇编语言学习笔记】 外中断
接口芯片和端口 在PC系统的接口卡和主板上,装有各种接口芯片。 这些外设接口芯片的内部有若干寄存器,CPU将这些寄存器当作端口来访问。 外设的输入不直接送入内存和CPU,而是送入相关的接口芯片的端口中。 CPU向外设输出也不是直接送入外设,而是先送入端口中,再由相关的芯片送到外设。 CPU还可以向外设输出控制命令,而这些控制命令也是先送到相关芯片的端口中,然后再由相关的芯片根据命令对外设实施控制。 CPU通过端口和外部设备进行联系。 外中断信息 在PC系统中,外中断源一共有两类: 1) 可屏蔽中断 可屏蔽中断中CPU可以不响就的外中断。 IF=1,则CPU在执行完当前指令后响应中断,引发中断过程。 IF=0,则不响应可屏蔽中断。 IF位于FLAG第9位。 关于中断所引发的中断过程: 1) 取中断类型码N 2) 标志寄存器入栈 IF=0,TF=0 3) CS、IP入栈 4) (IP)=(N*4), (CS)=(N*4+2) 可屏蔽中断所引发的中断过程,除与第1步实现上有所不同外,基本和内中断的中断过程相同。 因为可屏蔽中断信息来自于CPU外部,中断类型是通过数据总线送入CPU的。 而内中断的中断类型码是在CPU内部产生的。 将IF置0的原因:在进入中断处理程序后,禁止其他的可屏蔽中断。 如果在中断处理程序中需要处理可屏蔽中断,可以用指令将IF置1: 8086CPU提供设置IF指令: STI 用于设置IF=1 (允许响应中断) CLI 用于设置IF=0 (不响应中断) 2) 不可屏蔽中断 不可屏蔽中断是CPU必须响应的外中断。 对于8086CPU,不可屏蔽中断的中断类型码固定为2。 所以中断过程中,不需要取中断类型码。 不可屏蔽中断的中断过程为: 1) 标志寄存器入栈 IF=0, TF=0; 2) CS、IP入栈 3) (IP)=8, (CS)=(0AH) 几乎所有由外设引发的外中断,都是可屏蔽中断。 PC机键盘的处理过程 键盘输入的处理过程: 1) 键盘产生扫描码 2) 扫描码送入60H端口 3) 引发9号中断 4) CPU执行INT9中断例程处理键盘输入 上面第1、2、3步均由硬件完成。 BIOS键盘缓冲区是系统启动后,BIOS用于存放INT9中断例程所接收键盘输入的内存区,可存储15个键盘输入。 INT9中断例程除了接收扫描码外,还要产生和扫描码对应的字符码,所以BIOS键盘缓冲区中,一个键盘输入用一个字单元存放。 高位字节存放扫描码,低位字节存放字符码。 0040:17 单元存储键盘状态字节,该字节记录了控制键和切换键的状态。 显示从 a ~~ z : 简单延时-循环 显示从 a ~~ z 字母,每隔一定时间显示下一个字母 键盘输入到达60H端口后,就会引发9号中断,CPU则转去执行INT9中断例程。要求编写INT9中断例程,功能如: 1) 从60H端口读出键盘的输入 2) 调用BIOS的INT9中断例程,处理其他硬件细节 3) 判断是否为ESC键扫描码,如果是,改变显示的颜色后返回; 如果不是则直接返回。 编写自己的INT9中断例程,但原INT9有一些复杂的硬件细节处理,所以在我们自己的INT9中断例程中还要调用原INT9。 所以,在中断向量表内将INT9中断例程入口地址改写为我们自己的中断例程前,需要先保存原INT9。 当保存原INT9中断例程的偏移地址和段地址后,再调用它时就不能使用INT9来调用了。需要用别的指令来对INT指令进行模拟。 在用其它指令对INT指令进行模拟前,需要先看一下INT指令在执行的时候CPU是如何工作的: 1) 取中断类型码 N 2) 标志寄存器入栈 3) IF=0、 TF=0 4) CS、IP入栈 5) (IP)=(N*4), (CS)=(N*4+2) 取中断类型码是为了定位中断例程的入口地址。 但是,当我们将原INT9中断入口地址保存到另一个内存区域时,我们就不需要中断类型码了,因为我们知道那块自己指定的在内存在哪。 假设已将原INT9中断例程的入口地址保存到了 ds:0 与 ds:2 单元中。现在模拟int过程: 1) 标置寄存器入栈 2) IF=0、TF=0 3) CS、IP入栈 4) (IP)=((DS)*16+0) , (CS)=((CS)*16+2) 上面第3步是CS、IP入栈,因为如果不入栈调用完中断或是子程序就回不到调用者了。 不过,如果是引发INT中断例程的话,CPU是会帮我们做保存CS与IP(入栈)的,所以不用我们自己来。 可是,现在不是要调用INT中断例程,因为原INT9已被我们备份到另一个地址(它的入口地址已经不在中断向量表项中了)。所以我们如果需要调用INT9(就是要执行它,然后再返回到调用者处)就必须使用call命令。 而CALL命令有一个特点:执行CALL命令时,IP指向CALL命令下一条指令(为的是将来返回调用者继续执行CALL后面的指令)。如果CALL是段内CALL,则CPU将IP压栈(不用我们压,这个过程是CPU自动完成的);如果CALL是段间(即:CS:IP)方式,则CPU会自动压入CS、IP(都要压入,不然回不来了)。 所以,上面的CALL的过程和INT调用过程在压入CS、IP入栈的过程是一模一样的。 CALL与调用中断例程不一样的地方是:调用中断例程时CPU自动先压标志寄存器,然后…… 而CALL执行时CPU压IP或是CS:IP,但它并不压标志寄存器入栈。 所以如果想用CALL来模拟调用中断例程的方式使用存在另一块内存地址的 DS:0 和 DS:2 的原INT9中断例程,则需要我们: (1) 自己压入标志寄存器 (2) 自己设置IF=0,TF=0(这些得自己做,CALL指令不会帮我们做的,只有INT调用CPU才会帮我们做) (3) 使用 call dword ptr ds: 的方式(4字)调用原INT9入口地址,执行原INT9例程。 如何将标志寄存器入栈? pushf指令可以实现。 如何将标志寄存器的IF与TF的值设置为0? IF 标志寄存器的第9位 TF 标志寄存器的第8位 关于IF与TF的含义: IF 表示可屏蔽中断 TF 表示单步中断 为什么要禁止单步中断? 当TF=1(允许单步中断)时,CPU在执行完一条指令后将此发单步中断,转去执行中断处理程序。 而中断处理程序也是由一条条指令组成,如果在执行中断处理程序之前,TF=1,则CPU在执行完中断处理程序的第一条指令后又要产生单步中断,则又要转去执行单步中断的中断处理程序,在执行完中断处理程序的第一条指令后,又要产生单步中断,则又要转去执行单步中断的中断处理程序……无穷无尽的下去…… 所以,有时候必须将TF=0(设置为禁卡单步中断),这样才能正确的连续的执行需要的过程。 不可屏蔽的中断类型码固定为:2 中断过程中不需要取中断类型码。不可屏蔽中断过程的寻址部分: (IP)=(8), (CS)=(0AH) 其实上面的计算过程如下原理: (IP)=(2*4) (CS)=(2*4+2) 不可屏蔽中断是在系统中有必须处理的紧急情况发生时用来通知CPU的中断信息。 编程:在屏幕中间依次显示 a~~z ,延时处理显示在屏幕上。 在显示过程中,按下 Esc 键后,改变显示颜色。 ) 分析上面int9中断例程,精简指令 进入中断例程后,IF和TF都已经置0。 上面批令可以精简为: 精减后的全部代码如下: ) 分析上面主程序 在主程序中,如果执行设置INT9中断例程的段地址和篇移地址的指令之间发生了键盘中断, 则CPU将转去一个错误的地址并执行,将发生错误。 排除潜在错误的完全代码: 编程:安装新的 int 9 中断例程,使得原 int 9 中断例程的功能得到扩展。 在DOS下,按F1键后改变当前屏幕的显示颜色,其他的键照常处理。 在 Windows CMD 下调试先运行安装程序。然后进入一个16位程序界面(DEBUG、EDIT等),然后在里面按F1键有效。 此代码正常运行环境: MS-DOS 编程:安装新的 int 9 中断例程 在DOS下,按下 “A” 键后,除非不再松开,如果松开,就显示满屏幕 “A” ,其他键照常处理。 按下一个键时产生的扫描码称为通码。 松开一个键时产生的扫描码称为断码。 断码=通码+80H 上面的代码原理从个人理解角度讲,已经可以做好玩的东东了~:) 指令系统总结 1 数据传送指令 2 算术运算指令 3 逻辑指令 4 转移指令 5 处理机控制指令 6 串处理指令 [ Last edited by redtek on 2007-1-13 at 11:06 PM ] |
|
| 上一页 1 … 4 5 6 7 8 9 下一页 |
|
[ 联系联盟系统管理团队 -
中国DOS联盟 -
标准版 ] Sponsored by ifanr Inc | © 2001–2023 |