|
REGS 是声明(描述) Intel 80x86 CPU 16位通用寄存器的一个内部结构(还包括标志位寄存器,标志位寄存器一般用作设置或获得错误)。 一般的用途是: 向中断接口提供一个参数寄存器组。 该结构会在int86()函数、int86x() 函数、intdos() 函数及intdosx()函数中被使用到,这四个函数已在头文件 dos.h 中被声明,详细使用方法请网友自行参阅相关文档或书籍。 如果学过汇编的网友应该很容易地看懂,若没有学过汇编需要先去参考一下汇编相关入门书籍。 简而言之,80x86 16位通用寄存器包括: AX,BX,CX,DX,SI,DI,SP,BP(最后的 SP 和 BP)在C中没有被声明。 此外,AX,BX,CX,DX 分别分为高位字节(High)与低位字节(Low), 分别是(左边为高位字节,右边为低位字节): AX{AH,AL} BX{BH,BL} CX{CH,CL} DX{DH,DL} 无论是 16 位的寄存器(AX,BX ……),还是 16 位寄存器的高低位字节(8位宽)(AH,AL,BH,BL……), 并没有明确地说明各个寄存器的作用,而常规地,尤其在 CPU 中断指令等地方,那些寄存器有各自特定的用途。 在C语言中的 REGS 结构如下: union REGS { struct WORDREGS x; struct BYTEREGS h; }; 明显地,REGS 是由两个另外的结构封装而成,WORDREGS 结构及 BYTEREGS 结构。 而 WORDREGS 如下: struct WORDREGS { unsigned int ax, bx, cx, dx, si, di, cflag, flags; }; unsigned int 一般在16位字长CPU下的编译器被定义尺寸是16位(2字节)的。 ax,bx,cx,dx,si,di 在前面已有说明,而 cflag 与 flags 用于标志寄存器。 BYTEREGS 如下: struct BYTEREGS { unsigned char al, ah, bl, bh, cl, ch, dl, dh; }; 分别是前面说的各寄存器的高位字节与低位字节的描述,以 unsigned char 类型来声明是因为, 高位字节与低位字节都是8位宽。 声明一个 REGS 结构类型的变量后,如 REGS regs; 可以使用用 WORDREGS 结构的 x 来访问或设置16位寄存器,如 regs.x.dx = FP_OFF(FarVar); 使用 BYTEREGS 结构的 h 来访问16位寄存器的高位或低位字节,如 regs.h.ah = 9; 可能需要说明一下: FP_OFF 是一个宏,用于设置偏移地址,事实上,它的作用是转换 FarVar 这远指针为 unsigned int 类型。 此外还有 FP_SEG 宏,用于设置段地址,而该宏也是先将指针转换为32位无符号长整型(unsigned long)后,右移16位,将结果再转换为 unsigned int 类型。 下面会给出一个例程,该例程说明如何在 int86() 函数中使用 REGS 结构,而其它的函数可以参考相关的文档或书籍。 int86() 函数的功能是提供通用的 8086 软中断接口(关于中断信息,请自行参考相关文档或书籍)。 其原型是: int86(int intno, union REGS* inregs, union REGS* outregs); intno 参数指定中断号,inregs 与 outregs 分别是入口参数寄存器和出口参数寄存器。 入口参数提供信息,结果则从出口参数中获取——可能入口与出口是同一组寄存器,这是允许的。 下面的例程检测键盘的状态,判断哪些功能键(Shift, Alt, Ctrl, Num Lock, Caps Lock)被按下过。 程序调用int86()函数来使用 Int 16h 的功能2 —— 取键盘标志字节, 该功能把一字节值返回到 AX 的低位字节(AL 寄存器)中, 该字节各个位描述了键盘的功能键状态(On/Off) 下面的程序的用法说明一下,下面的程序在运行后, 按任意键开始检测,按小写 ‘q’结束; 开始只能看到 Num Lock, Caps Lock 及 Scroll Lock 三个功能开关的状态, 按任意键继续检测, 而如果想要检测到 Shift、Alt、Ctrl 这些功能键,需要按住它们,然后再按任意其它键,再松开所有键,即可被检测到, 需要注意的是,可能有些 Windows 组合键会被触发。如按住 Alt 然后按其它任意键开始检测,但是如果任意地刚好按中了 Space(空格), 那么将会激活窗口的系统菜单,所以尽量避免使用 Windows 的组合键。 #include #include #include #define RSHIFT 1 /* 右 Shift 键 */ #define LSHIFT 2 /* 左 Shift 键 */ #define CTRL 4 /* Ctrl 键 */ #define ALT 8 /* Alt 键 */ #define SCROLLLOCK 16 /* Scroll Lock 键 */ #define NUMLOCK 32 /* Num Lock 小键盘锁键*/ #define CAPSLOCK 64 /* Caps Lock 大小写转换状态键 */ int main(void) { int InNum = 0x16; union REGS InRegs; union REGS OutRegs; printf("Check the keyboard's status:\n"); /* 接收键盘输入 */ while( getch() != 'q' ) { clrscr(); printf("Check the keyboard's status:\n"); InRegs.h.ah = 2; int86(InNum, &InRegs, &OutRegs); /* 判断键盘状态 */ if ( OutRegs.h.al & RSHIFT ) puts("Right Shift"); if ( OutRegs.h.al & LSHIFT ) puts("Left Shift"); if ( OutRegs.h.al & CTRL ) puts("Ctrl"); if ( OutRegs.h.al & ALT ) puts("Alt"); if ( OutRegs.h.al & SCROLLLOCK ) puts("Scroll Lock (On)"); else puts("Scroll Lock (OFF)"); if ( OutRegs.h.al & NUMLOCK) puts("Num Lock (On)"); else puts("Num Lock (Off)"); if ( OutRegs.h.al & CAPSLOCK) puts("Caps Lock (On)"); else puts("Caps Lock (Off)"); } puts("\nPress any key to exit."); getch(); return 0; } |
|