首先让我们利用 IN 指令和 OUT 指令,来进行一个直接控制硬件的试验。假设该试验的目的是让计算机内配置的蜂鸣器(小喇叭)发音。虽然蜂鸣器内置在计算机内部,但其本身也是外围设备的一种因为就算是把蜂鸣器取出,对计算机主机也不会有什么影响。
由于用汇编语言编写程序比较麻烦,因此这里我们采取在 C 语言源代码中插入助记符的方式来实现。在大部分 C语言的处理(编译器的种类)中,只要使用_asm{ 和}括起来,就可以在其中记述助记符也就是说,这样就可以编写 C 语言和汇编语言混合的源代码。这里,我们使用微软的 Visual C++ 来作成应用。
在 AT 兼容机中,蜂鸣器的默认端口号是 61H(末尾的 H,表示的是十六进制数(Hexadecimal)的意思)。用IN 指令通过该端口号输人数据,并将数据的低2位设定为 ON,然后再通过该端口号用 OUT 指令输出数据,这时蜂鸣器就会响起来。采用同样的操作方法,将数据的低 2位设定为 OFF 并输出后,蜂鸣器就停止了。
位设定为 ON 指的是将该位设定为 1,位设定为 OFF 指的是将该位设定为 0。把位设定为 ON,只需把想要设定为 ON 的位设定为 1.其他位设定为0后进行 OR 运算即可。由于这里需要把低2位置为 1因此就是和 03H进行 OR 运算。03H用8位二进制数来表示的话是00000011。由于即便高6 位存在着具体意义,和0进行 OR 运算后也不会发生变化,因而就和 03H 进行 OR 运算。把位设定为 OFF,只需把想要置 OFF 的位设定为 0,其他位设定为 1后进行 AND 运算即可。由于这里需要把低2位设定为0,因此就要和FCH进行 AND 运算。在源代码中,FCH 是用 OFCH 来记述的。在前面加0是汇编语言的规定表示的是以 A~F 这些字符开头的十六进制数是数值的意思。OFCH 用8 位二进制数来表示的话是 11111100。由于即便高6位存在着具体意义,和1进行 AND 运算后也不会产生变化,因而就是同 OFCH 进行OR 运算(代码清单 11-2)。
接下来就让我们对代码清单 11-2 进行详细说明。main 是位于C语言程序运行起始位置的函数。在该函数中,有两个用 asm{ 和}围起来的部分,它们中间有一个使用 for 语法的空循环(不做任何处理的循环 )。
(1)部分是控制蜂鸣器发音的部分。首先,通过IN EAX,61H (助记符不区分大小写)指令,把端口 61H的数据存储到 CPU的 EAX寄存器中。接下来,通过 OR EAX03H 指令,把 EAX 寄存器的低2位设定成ON。最后,通过 OUT 61H,EAX 指令,把 EAX 寄存器的内容输出到 61 号端口,使蜂鸣器开始发音。虽然 EAX 寄存器的长度是 32位,不过由于蜂鸣器端口是 8 位,所以只需对下8位进行 OR 运算和AND 运算就可以正常运行了。
(2)部分是一个重复 100 万次的空循环,主要是为了在蜂鸣器开始发音和停止发音之间稍微加上一些时间间隔。因为现在计算机的CPU 运行速度非常快,哪怕是 100 万次的循环,也几乎是瞬间完成的。
(3)部分是用来控制蜂鸣器发音停止的部分。首先,通过 INEAX,61H指令,把端口 61H 的数据存储到 CPU的 EAX 寄存器中。接下来,通过 AND EAX,OFCH 指令,把 EAX寄存器的低2位设定成OFF。最后,通过 OUT 61HEAX 指令,把寄存器 EAX 的内容输出到61 号端口,使蜂鸣器停止发音。大家可以把 61H 端口的低 2 位认为是蜂鸣器的开关。
最后,让我们对代码清单 11-2 进行编译,并尝试运行一下。这时蜂鸣器应该会发出“嘀!”的短促声音。此外,有一点需要注意的是该程序虽然在旧版本 Windows (95、98)中可以正常运行,但在这以后的 Windows (XP、Vista 等)版本中是无法正常运行的。这是因为,为了保护系统安全,现在的 Windows 禁止了应用直接控制硬件的方式如果将该程序在最近的 Windows 版本上运行的话,就会出现如图 11-5所示的错误信息,而且蜂鸣器也不会发出声音。
标签:设定,蜂鸣器,运算,输入输出,11.3,EAX,61H,指令,编写 From: https://www.cnblogs.com/z1218/p/17100446.html