从物理层面解释,为什么在键盘上输入 abc,电脑屏幕上就会显示 abc?

从物理硬件角度分析一下这个过程从键盘到主机到屏幕都发生啦什么?首先从敲键盘开始,应该是产生了一个瞬间的电流,然后呢(゚O゚)
关注者
2,744
被浏览
959,766
登录后你可以
不限量看优质回答 私信答主深度交流 精彩内容一键收藏

从汇编的角度解释吧

我为什么用汇编解释呢,因为汇编是介于软件与硬件之间的东西,它的本质是0和1

0和1在逻辑电路上就是低电位与高电位

然而逻辑电路的东西在这一篇回答里又讲不完,所以就先讲汇编如何实现输入的实时屏幕输出吧

直接上代码吧

方便理解,用LC-3汇编来实现

LC-3有以下规则

16位地址和指令长度

常用寄存器为R0-R7,但人为编写时一般不会用R0和R7,后面你会知道为什么的

“;”是comment

如果单纯只是为了将输入的字符输出到屏幕,然后就halt那么只需占用两个内存地址

假设从x3000地址开始

代码就是

	.ORIG	x3000	;Indicate the starting address
LOOP	TRAP	x20	;Char R0 = Console.Read()
	TRAP	x21	;Console.Write(R0)
	TRAP	x25	
	.END		;End Program

x3000这个counter,其instruction是等待键盘输入一个字符,接收到字符后,该字符的ASCII值被储存到寄存器R0,结束,且PC+1,(PC的全称是Program Counter,其包含下一个将被执行的指令的地址)

假设我们输入“0”,那么,在x3000结束后,PC为x3001,R0为x0030(即0的ascii编码)

然后到x3001这个counter,其instruction是输出R0到屏幕,那么该instruction结束后,PC为x3002,屏幕显示ascii x30的字符即“0”

x3002,结束程序,其实可以不用这个TRAP x25,LC-3完全是给学生设计的,TRAP x25后,PC会调到预设定位置输出--------halting processor---------告诉你程序结束,这一行不要也行,但是后面的.end 一定是要有的

实际效果是这样的

https://www.zhihu.com/video/978632881849061376

那么如何实现多次输入并实时显示到屏幕呢

LC-3支持label,我们只需在敲代码时在x3000那里加个label比如叫LOOP

然后在x3002 写BRnzp指令(BR指令二进制解释如图)

n为negative,z为zero,p为positive,该指令将对R0判定,如果符合11-9的条件,就跳转到8-0位或label所指的地址

回到代码,代码如下

	.ORIG	x3000	;Indicate the starting address
LOOP	TRAP	x20	;Char R0 = Console.Read()
	TRAP	x21	;Console.Write(R0)
	BRnzp	LOOP	;unconditionally jump to LOOP
	.END		;End Program

我在这里写的是BRnzp,及11-9都为1,意味着R0<0 AND R0=0 AND R0>0时跳转到loop,就是无条件跳转到loop

那么你每次输入完并输出到屏幕后,执行完BR指令后都会跳回到LOOP,这其实就是循环结构,这种跳转指令,高级语言中的for啊,while啊,loop这些循环结构,if什么的判断,都是这么实现的

在这里很容易理解了,就是个不断输入输出的死循环,暂时先不考虑怎么跳出去,就是为了实现连续输入输出而已

演示如下

https://www.zhihu.com/video/978652764931313664

那么怎么跳出循环呢,在高级语言编程时,在运行最基本的console application的时候,比如Windows下的CMD,Linux的命令行界面下,最常见的都是输入一行指令并按回车键提交。大多数高级语言中比如C#的readline,等待用户键盘键入也都是在按回车时执行下一行。

其实很简单

回车,本质上也是一个字符,在ASCII中有对应的值,我们只需某一次输入有没有这个值就可以了

上面的BRnzp我们稍微修改一下

程序每次接收并实时输出所接收到的字符后

也就是执行完x3001后,x3002 来做一道简单的加减法,回车的ASCII值是x000A,也就是十进制的10

由于每次执行完x3001后,我们输入的字符的ASCII值都被保存在了R0中,那么就让R0-10,如果R0 = R0 - 10 =0,即可判定用户键入了回车键,程序要跳出循环往下走了

具体代码如下

	.ORIG	x3000		;Indicate the starting address
LOOP	TRAP	x20		;Char R0 = Console.Read()
	TRAP	x21		;Console.Write(R0)