x86汇编利用int 16h中断实现伪多线程输入

我们都知道,如果想让一个程序,同时又干这个,又干那个,最好的办法就是多线程。这个在高级语言里面已经用烂了。

但是,DOS是只有单线程的。我如果想让程序在运行的同时,又能接受我键盘的输入,那要怎么办呢?

例如,我有一个DOS彩票开奖软件。屏幕上有十个数字在滚动,当我按下空格键的时候,它会停止跳动,按别的键无效。那么要怎么操作?

首先,接收输入最常用的是int 21h中断里的7号功能调用。但是它是一个中断输入,也就是为了接收这个输入,我的程序就暂停在这儿不动了。但是我彩票开奖数字一直在滚动,那要怎么办啊?不能说我按一下它滚动一下吧。

于是请来了今天的主角,int16h中断。

首先我们看看int 16h中断有哪些功能?

BIOS提供了int 16h中断例程供程序员调用,且功能是从软件层面上实现键盘I/O功能中断调用,功能号为0,1,2,并且必须把功能号放在ah寄存器中。

0号功能调用

mov ah,01h
int 16h

功能:从键盘读入字符送进al寄存器,执行时,等待键盘输入,一旦输入,输入字符的ASCII码放入al中。若al为0,则ah为输入的扩展码。但是,如果键盘缓冲区已有数据,则会读取键盘缓冲区数据,并且将其从缓冲区中删除。

0号功能的工作流程为:

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

1号功能调用

mov ah,01h
int 16h

功能:用于查询键盘缓冲区,对键盘扫描但是不等待(也就是不会中断程序),并设置标志寄存器中的ZF。如果有键盘输入(即键盘缓冲区不空),则ZF=0,AL存放的是当前输入的ASCII码,AH存放的是输入字符的扩展码。若无键盘操作,则标志位ZF=1。

2号功能调用

mov ah,02h
int 16h

功能:检查键盘上各特殊功能键的状态。执行后,各种特殊功能键的状态放入AL寄存器中,这个状态字记录在内存0040H:0017H单元中,若对应位为“1”,表示该键状态为“ON”,处于按下状态;若对应位为“0”,表示该键状态为“OFF”,处于断开状态。

mov ah,02h
int 16h ;从键盘输入
and al,04h ;判断是否按下Ctrl
jnz Ctrl_on Ctrl_on:
......

了解了以上功能,我们来看如何实现伪多线程输入。

mainLoop:
mov ah,01h ;检测是否有输入
int 16h
jz offKey ;jz是当zf=1时跳转,也就是无输入
;如果有输入,没有跳转
mov ah,00h ;那么键盘缓冲区已不为空
int 16h
cmp al,32 ;和空格的ASCII码比较
je spaceProc
...
spaceProc:
...
offKey:
...

这个框架简单易懂,先从mainLoop中判断是否有输入:

  • 如果没有任何输入,则直接执行offKey中的代码内容;
  • 如果有输入,会调用0号功能对键盘缓冲区进行检索。因为我们已知它有输入(键盘缓冲区不为空),所以不会中断程序。
    • 如果键盘输入为空格,就跳转到spaceProc,否则再加别的代码。
    • 当然,我们可以利用这个做很多事情,不只是判断空格。

这样,利用int 16h中断中0号功能和1号功能的联动,我们实现了在只支持单线程的DOS中,实现了伪多线程的输入判断。

x86汇编利用int 16h中断实现伪多线程输入的更多相关文章

  1. x86汇编反编译到c语言之——(1)表达式求值及赋值语句

    一. 反编译一种可能的实现方式 我们的目的是将多种平台的汇编如x86,ARM,6502反编译为c语言,所以实现时先将多种汇编转化为 特定虚拟机汇编语言,然后只需要将虚拟机汇编语言反编译为c语言.其中多 ...

  2. x86汇编反编译到c语言之——(2)if语句

    一. 测试的C语句及编译后的x86汇编代码 int a; int b; int main(void) { int c; if (c) a = 4; else b = 5; return 0; } 1 ...

  3. 安装新的int 9中断例程

    body, table{font-family: 微软雅黑; font-size: 13.5pt} table{border-collapse: collapse; border: solid gra ...

  4. 汇编实验15:安装新的int 9中断例程

    汇编实验15:安装新的int 9中断例程 任务 安装一个新的int 9中断例程,功能:在DOS下,按下“A”键后,除非不在松开,一旦松开后,就显示满屏幕的“A”,其他键照常处理. 预备知识概要 这次实 ...

  5. 汇编试验十五:安装新的int 9中断例程

    安装新的int 9中断例程(按'A'键后显示满屏幕的'A') int 9 是外中断,同样,程序编写还是和其他中断例程类似,安装(复制),调用: 不同点是在于,他要从端口读取数据60h, Source ...

  6. C# inline-asm / 嵌入x86汇编

    C#可不可以嵌入汇编 可以 在我眼中C#作为一个介于中上层语言是不可能不可以 置入汇编代码的 为什么会被我认为中上层语言呢 从C#保留指针就可以看出 我知 道有很多人一定不会相信C#可以使用汇编代码 ...

  7. x86汇编之十(使用字符串)

    x86汇编之十(使用字符串) 转自网络,出处不详 一.传送字符串 Intel提供了完整的字符串传送指令,就像是MOV指令一样. 1.MOVS指令 1)movs指令格式 把字符串从一个位内存位置传送到另 ...

  8. 对X86汇编的理解与入门

    本文描述基本的32位X86汇编语言的一个子集,其中涉及汇编语言的最核心部分,包括寄存器结构,数据表示,基本的操作指令(包括数据传送指令.逻辑计算指令.算数运算指令),以及函数的调用规则.个人认为:在理 ...

  9. 寄存器理解 及 X86汇编入门

    本文整理自多材料源,感谢原址分享,请查看末尾Url I, 汇编语言分类: 汇编语言和CPU息息相关,但是不能把汇编语言完全等同于CPU的机器指令.不同架构的CPU指令并不相同,如x86,powerpc ...

随机推荐

  1. PHP的json_encode和json_decode的区别

    经常搞混的两个PHP函数: json_encode()是对变量进行json编码 json_encode()为要编码的值,且该函数只对utf8编码的数据有效 json_decode($json)对jso ...

  2. Redis02——Redis内存数据如何保存到磁盘

    在前一篇文章中,已经介绍了Redis的基础数据结构,这篇文章将继续介绍Redis的持久化原理. 简介 众所周知Redis的所有数据都存在于内存之中,这就会存在因内存问题而导致的数据丢失,为了避免这一问 ...

  3. asyncio在爬虫中的使用

    # -*- coding: utf-8 -*- # 协程基础.py import asyncio import time async def request(url): print("正在请 ...

  4. Go语言之Go语言变量

    GO 语言变量 Go语言是静态类型语言,因此变量(variable)是有明确类型的,编译器也会检查变量类型的正确性. 标识符 在编程语言中标识符就是程序员定义的具有特殊意义的词,比如变量名.常量名.函 ...

  5. Symantec(赛门铁克)非受管检测

    为了查找局域网内没有安装赛门铁克客户端的IP,采用Symantec Endpoint Protect Manager 的非受管检测机制进行网段扫描. 非受管检测机制的原理是:每台电脑开机时都会向同网段 ...

  6. dom&JavaScript&Jquery

    目录 dom&JavaScript&Jquery 建节点 添加节点 删除节点: 替换节点: 属性节点 获取值操作 class的操作 指定CSS操作 操作节点 获取input用户输入 操 ...

  7. ASP.NET动态网站课程设计——个人网页

    时光荏苒,岁月如梭,又是学期期末时,没错,我又来补课程设计了,hhh. 本文主要讲述如何在用H5+CSS3写的静态网站的基础上,结合ASP.NET动态网站开发,制作一个动态的个人网页. 首先需要熟悉一 ...

  8. PTA 创建计算机类

    6-5创建计算机 (10分) 定义一个简单的Computer类,有数据成员芯片(cpu).内存(ram).光驱(cdrom)等等,有两个公有成员函数run.stop.cpu为CPU类的一个对象,ram ...

  9. git的cd命令

    这个命令是进入某个文件夹的命令.进入文件夹后可以对文件夹中的文件进行一系列操作.

  10. OpenCV-Python 图像阈值 | 十五

    目标 在本教程中,您将学习简单阈值,自适应阈值和Otsu阈值. 你将学习函数cv.threshold和cv.adaptiveThreshold. 简单阈值 在这里,问题直截了当.对于每个像素,应用相同 ...